import { eventTarget, PLAY_ROLLING_SOUND, ROTATE_GUILD, STOP_GUILD_ROTATE } from "../Events";
import { TrackEntry } from "../Utils";

const { ccclass, property } = cc._decorator;

@ccclass
export default class HuController extends cc.Component {
    @property(sp.Skeleton)
    private spine2: sp.Skeleton = null;

    private _spine: sp.Skeleton = null;
    private _pointStart: cc.Vec2 = null;
    private _x: number = 0;
    private _y: number = 0;
    private _z: number = 0;
    private _count = 0;
    private _isShake = false;
    private _track: TrackEntry = null;

    protected onLoad(): void {
        this._spine = this.node.getComponent(sp.Skeleton);

        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_MOVE, this.onTouchMove, this)
        eventTarget.on(ROTATE_GUILD, this.onRotateGuild, this);

        this._spine.setCompleteListener(() => {
            console.log('setCompleteListener',)
            this.setRotateAnim();
        });

        this.scheduleOnce(this.setDeviceMotion, 2);

        this.initBottle();
    }

    private onRotateGuild() {
        this._spine.timeScale = 0.5;
        this.scheduleOnce(() => {
            this._track.trackTime = this._track.animationEnd / 4;
            this._spine.timeScale = 0;
        }, 1.2);
    }

    private initBottle() {
        this.setRotateAnim();
        let state = this._spine.getState();
        this._track = state.tracks[1];
        this._track.trackTime = this._track.animationEnd / 4;
        this._spine.timeScale = 0;
    }

    private onTouchStart(event: cc.Event.EventTouch): void {
        eventTarget.emit(STOP_GUILD_ROTATE);

        // if (!this._pointStart) {
        //     this.setRotateAnim();
        // }
        this._pointStart = event.getLocation();
        this._spine.timeScale = 0;
    }

    private onTouchEnd(): void {
        this.scheduleOnce(() => this._spine.timeScale = 0, 0.5);

        let state = this._spine.getState();
        let track = state.tracks[1];
        if (track.trackTime < 0) {
            track.trackTime = 0;
        }
    }

    private onTouchMove(event: cc.Event.EventTouch): void {
        const newPoint = event.getLocation();
        const distance = newPoint.x - this._pointStart.x;
        if (Math.abs(distance) < 5) {
            this._spine.timeScale = 0;
            return;
        }

        this._pointStart = newPoint;
        this._spine.timeScale = distance > 0 ? -1 : 1;
    }

    private setRotateAnim(): void {
        this._spine.setAnimation(1, "Rotate", false);
        this._spine.timeScale = this._pointStart ? 0 : 0.5;
    }

    private setDeviceMotion() {
        window.addEventListener("devicemotion", (event) => {
            if (!event.accelerationIncludingGravity) {
                return;
            }

            const x = event.accelerationIncludingGravity.x;
            const y = event.accelerationIncludingGravity.y;
            const z = event.accelerationIncludingGravity.z;

            if (x - this._x > 5 || y - this._y > 5 || z - this._z > 5) {
                if (this._isShake) {
                    this._count++;
                }
            }

            if (x - this._x < -5 || y - this._y < -5 || z - this._z < -5) {
                if (!this._isShake) {
                    this._count++;
                }
            }

            if (this._count > 0) {
                this.scheduleOnce(() => {
                    this._count = 0;
                }, 2)
            }

            if (this._count > 5) {
                this._count = 0;
                this.shakeBottle();
            }

            this._x = x;
            this._y = y;
            this._z = z;
        });
    }

    private shakeBottle() {
        eventTarget.emit(PLAY_ROLLING_SOUND);
        cc.tween(this.node)
            .repeat(5, cc.tween(this.node)
                .call(() => this.vibratePhone())
                .to(0.2, { position: cc.v3(40, this.randomY(), 0) })
                .to(0.2, { position: cc.v3(-40, this.randomY(), 0) })
            )
            .to(0.2, { position: cc.v3(0, 0, 0) })
            .start();
    }

    private vibratePhone() {
        if ("vibrate" in navigator) {
            navigator.vibrate(200);
        }
    }

    private randomY(): number {
        return Math.random() * 100 - 50;
    }
}
