﻿
@Component
export default class FlyIcon extends Script {
    public static instance: FlyIcon

    protected onStart(): void {
        if (SystemUtil.isServer()) { return }
        FlyIcon.instance = this
        this.useUpdate = true

        // 需要先创建一个
        let image = this.getImage()
        this._imagePool.push(image)
        image.visibility = SlateVisibility.Hidden
    }
    protected onUpdate(dt: number): void {
        TweenUtil.TWEEN.update()
    }

    /**用来显示所有Icon的UI对象 */
    private _uiWidget: UserWidget
    /*用来显示所有Icon的画布 */
    private _rootCanvas: Canvas

    /**图片的对象池 */
    private _imagePool: Image[] = [];

    /**坐标缓存 */
    private _tempPos: Vector2 = Vector2.zero;


    /**
     * 创建一个图片，并飞向指定图片
     * @param position 起始位置
     * @param targetIcon 目标图片
     * @param direction 方向（1代表往右偏移，-1代表往左偏移）
     */
    public flyToIcon(position: Vector | Vector2, targetIcon: Image, direction: number = 1) {

        let bornPos: Vector2 = null

        // 2D坐标则直接使用，3D坐标则进行转换
        if (position instanceof Vector2) {
            bornPos = position
        } else if (position instanceof Vector) {
            bornPos = InputUtil.projectWorldPositionToWidgetPosition(position, true).screenPosition;
        }

        let image = this.getImage()

        // 获取此时按钮的绝对位置
        const targetAbs = targetIcon.cachedGeometry.getAbsolutePosition()

        // 获取根画布的绝对位置
        const rootAbs = this._rootCanvas.cachedGeometry.getAbsolutePosition()

        // 计算差值,从而获取到目标图片相对根画布的位置
        let targetPos = targetAbs.subtract(rootAbs)
        // 获取DPI scale
        const dpiScale = mw.getViewportScale()

        // 消除DPI的影响
        targetPos.x /= dpiScale
        targetPos.y /= dpiScale

        // 起始位置对象
        const startPos = { x: bornPos.x, y: bornPos.y }
        // x方向上的偏移值
        const xOffset = 800 * direction + Math.random() * 200
        // y方向上的偏移值
        const yOffset = 600 + (Math.random() > 0.5 ? 1 : -1) * Math.random() * 400
        // 终点坐标（过程是先移动到偏移值的位置，然后再移动到目标位置）
        const endPos = { x: [bornPos.x + xOffset, targetPos.x], y: [bornPos.y + yOffset, targetPos.y] }

        let animator = new Tween(startPos).to(endPos, 1000).onUpdate((v) => {
            this._tempPos.set(v.x, v.y)
            image.position = this._tempPos
        }).onStart(() => {
            // 让图片、大小、角度都保持一致
            image.imageGuid = targetIcon.imageGuid
            image.size = targetIcon.size;
            image.renderTransformAngle = targetIcon.renderTransformAngle
            image.visibility = SlateVisibility.SelfHitTestInvisible
        }).onComplete(() => {
            image.visibility = SlateVisibility.Hidden
            this._imagePool.push(image);
        }).interpolation(TweenUtil.Interpolation.Bezier)

        animator.start();
    }


    /**
     * 创建多个图片飞向指定图片
     * @param position 起始位置
     * @param targetIcon 目标图片
     * @param count 数量
     * @param time 总耗时（单位/s）
     */
    public async flyToIconMultiple(position: Vector | Vector2, targetIcon: Image, count: number, time: number = 1) {
        let dir = 1
        for (let i = 0; i < count; i++) {
            await TimeUtil.delaySecond(time / count)
            FlyIcon.instance.flyToIcon(position, targetIcon, dir)
            dir = dir == 1 ? -1 : 1
        }
    }

    private getImage() {
        let image = this._imagePool.pop();
        if (image == null) {
            // 首次创建，如果没有UI对象，就创建一个
            if (!this._uiWidget) {
                // 创建一个UI对象
                this._uiWidget = UserWidget.newObject();
                this._uiWidget.addToViewport(1)
                // 首次创建，如果没有rootCanvas，就创建一个
                if (!this._rootCanvas) {
                    this._rootCanvas = Canvas.newObject()
                    this._rootCanvas.size = new Vector2(1920, 1080);
                    this._rootCanvas.position = Vector2.zero
                    this._uiWidget.rootContent = this._rootCanvas
                }
            }
            // 创建一个图片，并添加到画布上
            image = Image.newObject(this._rootCanvas)
        }
        return image
    }

}