import { tmCv } from ".";
import { color } from "./color";
import { shapeStyle } from "./interface";
import { division, addition, multiply, subtract, uuid } from "./util";

export class Shape {
    id: string = uuid(16)

    x: number = 0;
    y: number = 0;
    width: number = 0;
    height: number = 0;
    fillStyle: string = 'rgba(0,0,0,0)';
    strokeStyle: string = 'rgba(0,0,0,0)';
    lineWidth: number = 0;
    lineDashOffset: number = 0
    lineDash: number[] = [0]
    sAngle: number = 0
    eAngle: number = 0
    radius: [number, number, number, number] = [0, 0, 0, 0]
    /**一些圆弧等用到的内半径 */
    r: number = 0
    /**圆环时可能用到的内半径 */
    innerRadius: number = 0
    lineCap: any = 'round'
    lineJoin: any = 'round'
    textMaxWidth: number = 0
    /** 字符间距不支持断行 */
    letterSpace: number = 0
    text: string = ''
    playing: boolean = false;
    fontSize: number = 14
    textAlign: 'left' | 'right' | 'center' = 'left'

    canvas: tmCv
    constructor(tmcv: tmCv, arg: Partial<shapeStyle>) {
        for (const item in arg) {
            // @ts-expect-error
            this[item] = arg[item]
            // @ts-expect-error
            this['back_' + item] = arg[item]
        }
        this.canvas = tmcv;
        this.draw()
    }
    /**绘制 */
    draw<T>(arg?: shapeStyle) {
        return this
    }
    /**动画 */
    public animate(arg: Partial<shapeStyle>, animateConfig?: {
        /**动画时长 */
        duration?: number,
        /**重复次数 */
        repeat?: number,
        /**是否来回动画0-1，1-0这样的过渡效果 */
        yoyo?: boolean
    }) {
        const config = {
            duration: 500,
            repeat: 0,
            yoyo: false,
            onStart: () => { },
            ...(animateConfig || {})
        }
        this.playing = true;

        return this.canvas.animation(config, (progress: number) => {
            // 计算动画过程中矩形的位置和颜色
            let { x, y, width, height, radius, eAngle, sAngle, textMaxWidth, letterSpace, fontSize } = this;
            if (typeof arg.x !== 'undefined') {
                const baseX = this['back_x'] ?? 0;
                x = baseX + Number(arg.x - baseX) * progress

            }
            if (typeof arg.y !== 'undefined') {
                const baseY = this['back_y'] ?? 0;
                y = baseY + Number(arg.y - baseY) * progress
            }
            if (typeof arg.width !== 'undefined') {
                const baseWidth = this['back_width'] ?? 0;
                width = baseWidth + Math.abs((arg.width - baseWidth) * (progress))
            }
            if (typeof arg.width !== 'undefined') {
                const baseHeight = this['back_height'] ?? 0;
                height = baseHeight + Math.abs((arg.height - baseHeight) * (progress))
            }
            if (typeof arg.radius !== 'undefined' && radius) {
                this.radius = multiply(arg.radius, progress)
            }
            if (typeof arg.eAngle !== 'undefined' && eAngle) {
                this.eAngle = Number(arg.eAngle) * progress
            }
            if (typeof arg.sAngle !== 'undefined' && sAngle) {
                this.sAngle = Number(arg.sAngle) * progress
            }
            if (typeof arg?.textMaxWidth !== 'undefined') {
                this.textMaxWidth = Number(arg.textMaxWidth) * progress
            }
            if (typeof arg?.letterSpace !== 'undefined' && letterSpace) {
                this.letterSpace = Number(arg.letterSpace) * progress
            }
            if (typeof arg?.fontSize !== 'undefined') {
                const baseFontSize = this['back_fontSize'] ?? 14;
                this.fontSize = baseFontSize + (Number(arg.fontSize) - baseFontSize) * progress

            }

            if (typeof arg.fillStyle !== 'undefined') {
                const [rgbastr, rgba] = color.convertColorToRGBA(arg.fillStyle);
                const [s_rgbas, s_rgba] = color.convertColorToRGBA(this['back_fillStyle']);
                const rgbaResult = subtract(s_rgba, rgba, true)
                rgbaResult[0] = s_rgba[0] + progress * rgbaResult[0]
                rgbaResult[1] = s_rgba[1] + progress * rgbaResult[1]
                rgbaResult[2] = s_rgba[2] + progress * rgbaResult[2]
                rgbaResult[3] = s_rgba[3] + progress * rgbaResult[3]
                this.fillStyle = `rgba(${rgbaResult[0]},${rgbaResult[1]},${rgbaResult[2]},${rgbaResult[3]})`
            }
            if (typeof arg.strokeStyle !== 'undefined') {
                const [rgbastr, rgba] = color.convertColorToRGBA(arg.strokeStyle);
                const [s_rgbas, s_rgba] = color.convertColorToRGBA(this['back_strokeStyle']);
                const rgbaResult = subtract(s_rgba, rgba, true)
                rgbaResult[0] = s_rgba[0] + progress * rgbaResult[0]
                rgbaResult[1] = s_rgba[1] + progress * rgbaResult[1]
                rgbaResult[2] = s_rgba[2] + progress * rgbaResult[2]
                rgbaResult[3] = s_rgba[3] + progress * rgbaResult[3]
                this.strokeStyle = `rgba(${rgbaResult[0]},${rgbaResult[1]},${rgbaResult[2]},${rgbaResult[3]})`
            }
            this.x = x
            this.y = y
            this.width = width
            this.height = height
            this.canvas.draw()

        }).then(() => {
            this.playing = false;
            return Promise.resolve(this)
        })
    }
}