import { BEAT_GUILD, CHECK_FRAGMENT, CHECK_TOUCH, DROP_ALL_FRAGMENT, eventTarget, HAMMER, PLAY_BREAKING_SOUND, RESET_BOTTLE, RESET_FRAGMENT, SHAKE_FRAGMENT, SHOW_CARD_POPUP, SHOW_FOG, START_GUILD_TAP, STOP_GUILD_TAP } from "../Events";
import BehindFragment from "./BehindFragment";
import FragmentJarController from "./FragmentJarController";

const { ccclass, property } = cc._decorator;

@ccclass
export default class BreakingJarController extends cc.Component {
    @property(cc.Node)
    private hammerNode: cc.Node = null;
    @property(cc.Node)
    private behindJar: cc.Node = null;
    @property(cc.ParticleSystem)
    private particleFont: cc.ParticleSystem = null;
    @property(cc.ParticleSystem)
    private particleBehind: cc.ParticleSystem = null;
    @property(cc.Node)
    private mask: cc.Node = null;

    private _countFragment = 0;

    private _fragmentsPosition: cc.Vec3[] = [];
    private _fontFragments: cc.Node[] = [];
    private _bodyFragments: string[] = [];
    private _isEnd = false;
    private _behindJarChild: BehindFragment[] = [];
    private _behindJarChildPosition: cc.Vec3[] = [];
    private _hamerAvatar: cc.Sprite = null;
    private _isBreak = true;

    onLoad() {
        cc.director.getPhysicsManager().enabled = true;

        // cc.director.getPhysicsManager().debugDrawFlags = cc.PhysicsManager.DrawBits.e_aabbBit |
        //     cc.PhysicsManager.DrawBits.e_jointBit |
        //     cc.PhysicsManager.DrawBits.e_shapeBit;

        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);

        eventTarget.on(CHECK_FRAGMENT, this.checkFragment, this);
        eventTarget.on(HAMMER, this.onHammer, this);
        eventTarget.on(RESET_BOTTLE, this.resetBottle, this);
        eventTarget.on(BEAT_GUILD, this.beatGuild, this);
        eventTarget.on(SHOW_FOG, this.showFog, this);

        this._fontFragments = this.getComponentsInChildren(FragmentJarController).map(item => item.node);
        this._fragmentsPosition = this._fontFragments.map(item => item.position.clone());
        this._behindJarChild = this.behindJar.children.map(item => item.getComponent(BehindFragment));
        this._behindJarChildPosition = this.behindJar.children.map(item => item.position.clone());
        this._hamerAvatar = this.hammerNode.getComponentInChildren(cc.Sprite);

        this.initFog();
    }

    protected start(): void {
        this.resetHammer();
        eventTarget.emit(START_GUILD_TAP);
    }

    private initFog() {
        this.particleBehind.node.active = false;
        this.particleFont.node.active = false;
        this.particleFont.stopSystem();
        this.particleBehind.stopSystem();
        this.mask.opacity = 0;
    }

    private showFog(position: cc.Vec3) {
        if (this._countFragment > 0) {
            return;
        }

        this.particleFont.node.active = true;
        this.particleBehind.node.active = true;
        this.particleFont.node.position = position;
        this.particleFont.resetSystem();
        this.particleBehind.resetSystem();

        this.mask.active = true;
        this.mask.opacity = 200;
        this.mask.scale = 1;

        cc.tween(this.mask)
            .to(2, { scale: 1.5 })
            .to(5, { opacity: 255, scale: 2 })
            .start();
    }

    private checkFragment(fragmentNode: cc.Node) {
        if (this._isEnd) {
            return;
        }

        this._bodyFragments.push(fragmentNode.name);
        this._countFragment++;

        if (this._countFragment == 2) {
            cc.tween(this.mask)
                .to(1, { opacity: 200 })
                .start();
        }

        // return;

        if (this._countFragment == 3) {
            this.particleFont.stopSystem();
            this.particleBehind.stopSystem();
            cc.Tween.stopAllByTarget(this.mask);

            cc.tween(this.mask)
                .to(1.5, { opacity: 0 })
                .call(() => {
                    eventTarget.emit(DROP_ALL_FRAGMENT);
                    this._behindJarChild.forEach(item => item.onDrop());
                })
                .delay(2)
                .call(() => eventTarget.emit(SHOW_CARD_POPUP))
                .start();

            this._isEnd = true;
        }
    }

    private beatGuild() {
        this.onHammer(cc.v2(-50, -50));
    }

    private resetBottle() {
        this._countFragment = 0;
        this._bodyFragments = [];

        this._fontFragments.forEach((node, index) => {
            node.position = this._fragmentsPosition[index];
        })

        this._behindJarChild.forEach((behindFragment, index) => {
            behindFragment.node.position = this._behindJarChildPosition[index];
            behindFragment.reset();
        })

        eventTarget.emit(RESET_FRAGMENT);
        this._isEnd = false;
        this.initFog();
    }

    private onHammer(newPos: cc.Vec2) {
        this.hammerNode.active = true;
        cc.Tween.stopAllByTarget(this.hammerNode);

        cc.tween(this.hammerNode)
            .to(0.5, { position: cc.v3(newPos.x, newPos.y, 0) })
            .call(() => this.shakeNode())
            .delay(0.1)
            .to(0.2, { position: cc.v3(400, -400) })
            .call(() => this.hammerNode.active = false)
            .start();

        cc.tween(this._hamerAvatar.node)
            .delay(0.2)
            .to(0.2, { angle: -90 })
            .to(0.05, { angle: 0 })
            .call(() => eventTarget.emit(PLAY_BREAKING_SOUND))
            .start();
    }

    private shakeNode() {
        cc.director.getPhysicsManager().enabled = false;
        eventTarget.emit(SHAKE_FRAGMENT);
        cc.tween(this.node)
            .delay(0.15)
            .call(() => cc.director.getPhysicsManager().enabled = true)
            .start();
    }

    private onTouchStart(event: cc.Event.EventTouch) {
        eventTarget.emit(STOP_GUILD_TAP);
        const pos = event.getLocation();
        const nodePos = this.node.convertToNodeSpaceAR(pos);

        if (!this._isBreak) {
            return;
        }

        eventTarget.emit(CHECK_TOUCH, nodePos);
        this._isBreak = false;
        this.scheduleOnce(() => this._isBreak = true, 0.5);
    }

    private onTouchEnd(event: cc.Event.EventTouch) {

    }

    private resetHammer() {
        this.hammerNode.position = cc.v3(300);
        this.hammerNode.active = false;
    }
}
