const { ccclass, requireComponent, menu, property } = cc._decorator;

@ccclass
@menu("Plug-in/Button/HoldButton")
@requireComponent(cc.Button)
export default class HoldButton extends cc.Component {
    //#region public

    @property()
    public MaxTime: number = 2;

    /** 是否HoldLine */
    @property({ displayName: "是否有HoldLine", tooltip: "是否HoldLine" })
    public IsHaveHoldLine: boolean = false;

    @property({ type: cc.Node, visible(): boolean { return this.IsHaveHoldLine; } })
    public HoldLine: cc.Node = null;

    @property({ type: cc.Sprite, visible(): boolean { return this.IsHaveHoldLine; } })
    public ProgressBG: cc.Sprite = null;

    @property({ type: cc.Sprite, visible(): boolean { return this.IsHaveHoldLine; } })
    public ProgressLine: cc.Sprite = null;

    @property({ type: [cc.Component.EventHandler] })
    public OnInvoke: cc.Component.EventHandler[] = [];

    //#endregion

    //#region private

    private _isOnInvoke: boolean = false;

    private _m_isMouseDown: boolean = false;

    private _m_pressDeltaTime: number = 0;

    //#endregion

    //#region Lifecycle

    protected start(): void {
        if (this.HoldLine != null) {
            this.HoldLine.active = false;
        }
    }

    protected update(dt: number): void {
        if (this._m_isMouseDown) {
            this._checkHoldAutoStart(dt);
        } else {
            if (this.IsHaveHoldLine) {
                this.HoldLine.active = false;
            }
        }
    }

    protected onEnable(): void {
        this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
    }

    protected onDisable(): void {
        this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
        this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnd, this);
        this.node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
    }

    //#endregion

    //#region Custom

    private _checkHoldAutoStart(deltaTime: number): void {
        this._m_pressDeltaTime += deltaTime;

        if (this.IsHaveHoldLine) {
            // 蓄能條顯示特效
            this.ProgressLine.fillRange = this._m_pressDeltaTime;
        }

        if (this._m_pressDeltaTime > this.MaxTime) {
            this.node.pauseSystemEvents(true);

            this._isOnInvoke = true;
            this._m_isMouseDown = false;
            if (this.IsHaveHoldLine) {
                this.HoldLine.active = false;
            }
            this._m_pressDeltaTime = 0;
            if (this.OnInvoke != null) {
                this.OnInvoke.forEach((eventHandler: cc.Component.EventHandler) => {
                    if (eventHandler) {
                        if (eventHandler.target === <any>"Callback" && eventHandler.component === "Callback" && eventHandler.handler) {
                            (<Function><unknown>eventHandler.handler)();
                        } else {
                            eventHandler.emit([this.node.getComponent(cc.Button)]);
                        }
                    }
                });
            }
        }
    }

    //#endregion

    //#region EventT

    private _onTouchStart(event: cc.Event.EventTouch): void {
        if (this._m_isMouseDown) {
            return;
        }
        this._m_isMouseDown = true;
        if (this.IsHaveHoldLine) {
            this.HoldLine.active = true;
        }
    }

    private _onTouchEnd(event: cc.Event.EventTouch): void {
        this.node.resumeSystemEvents(true);
        this._m_isMouseDown = false;
        this._m_pressDeltaTime = 0;
        if (this.IsHaveHoldLine) {
            this.HoldLine.active = false;
        }
        this._isOnInvoke = false;
        this._checkHoldAutoStart(0);
    }

    private _onTouchCancel(event: cc.Event.EventTouch): void {
        this.node.resumeSystemEvents(true);
        this._m_isMouseDown = false;
        this._m_pressDeltaTime = 0;
        if (this.IsHaveHoldLine) {
            this.HoldLine.active = false;
        }
        this._isOnInvoke = false;
        this._checkHoldAutoStart(0);
    }

    //#endregion
}