import { find, instantiate, macro, Node, ScrollView, sp, Sprite, tween, Tween, UITransform, v2, _decorator } from 'cc';
import { BaseLayer } from '../../common/BaseLayer';
import { cocosUtil } from '../../utils/cocosUtil';
import { utilTools } from '../../utils/utilTools';
import { constants } from '../data/constants';
import { msgac } from '../data/msgac';
import { ItemLayer } from '../item/ItemLayer';
import { designManager } from '../manager/designManager';
import { eventManager } from '../manager/eventManager';
import { iconManager } from '../manager/iconManager';
import { levelManager } from '../manager/levelManager';
import { sdkManager } from '../manager/sdkManager';
import { playerModel } from '../model/playerModel';
import { FlutterEffect } from './effect/FlutterEffect';
import { ReelEffect } from './effect/ReelEffect';
import { FightLayer } from './FightLayer';
const { ccclass, property } = _decorator;

@ccclass('LevelLayer')
export class LevelLayer extends BaseLayer {

    listScrollView: ScrollView;
    listContentLayer: Node;
    levelLayer: Node;
    playerLayer: Node;
    skillEffectLayer: Node;

    hitEffectLayer: Node;

    btnAdAtk: Node;
    btnSkip: Node;

    levelNode: Node;
    level: number;

    handNode: Node;
    skillLayer: Node;
    fightLayer: Node;

    cloundLayer1: Node;
    cloundLayer2: Node;

    onLoad() {
        super.onLoad();

        this.getNodeByPath("cloundLayer").addComponent(FlutterEffect);
        this.getNodeByPath("moutainLayer").addComponent(ReelEffect);

        this.cloundLayer1 = this.getNodeByPath("list/view/content/cloundLayer1");
        this.cloundLayer1.addComponent(FlutterEffect).speed = 70;
        this.cloundLayer2 = this.getNodeByPath("list/view/content/cloundLayer2");
        this.cloundLayer2.addComponent(FlutterEffect).speed = 80;

        this.levelNode = this.getNodeByPath("level/level");
        this.btnAdAtk = this.getNodeByPath("btnAdAtk");
        this.btnSkip = this.getNodeByPath("btns/btnSkip");

        this.listScrollView = this.getNodeByPath("list").getComponent(ScrollView);
        this.listContentLayer = this.getNodeByPath("list/view/content");
        this.levelLayer = this.getNodeByPath("list/view/content/levelLayer");
        this.playerLayer = this.getNodeByPath("list/view/content/playerLayer");
        this.skillEffectLayer = this.getNodeByPath("list/view/content/skillEffectLayer");

        this.hitEffectLayer = this.getNodeByPath("hitEffectLayer");
        this.hitEffectLayer.addComponent(ItemLayer);

        this.skillLayer = this.getNodeByPath("skillLayer");
        this.skillLayer.addComponent(ItemLayer);

        this.fightLayer = this.getNodeByPath("fightLayer");
        this.fightLayer.addComponent(FightLayer);
        this.fightLayer.active = false;

        this.level = this.obj.level;

        this.initUI();

    }

    onEnable() {
        this.addEventArr([
            msgac.levelRestart,
            msgac.lifeBack,
            msgac.adjustPlayerInCenter,
            msgac.levelNext,
            msgac.levelEspSuccess,
            msgac.skillLayerRefresh,
            msgac.judgeLevelSuccess,
            msgac.showHitEffect,
            msgac.startFight,
            msgac.fightEnd,
            msgac.skillAdd,
            msgac.LevelLayerClose,
        ]);
    }

    onDisable() {
        this.removeEventArr([
            msgac.levelRestart,
            msgac.lifeBack,
            msgac.adjustPlayerInCenter,
            msgac.levelNext,
            msgac.levelEspSuccess,
            msgac.skillLayerRefresh,
            msgac.judgeLevelSuccess,
            msgac.showHitEffect,
            msgac.startFight,
            msgac.fightEnd,
            msgac.skillAdd,
            msgac.LevelLayerClose,
        ]);
    }

    initUI() {
        this.initEffect();

        this.initSkillLayer();
        this.schedule(() => {
            let arr = this.skillLayer.children;
            for (let i in arr) {
                let node = arr[i];
                Tween.stopAllByTarget(node);
                node.setRotationFromEuler(0, 0, 0);
            }
            let pNode = utilTools.getRandomItemByArr(arr);
            cocosUtil.tweenShake(pNode, 0.1, 0, 0);
        }, 0.4 * 5, macro.REPEAT_FOREVER, 0);

        this.loadLevelLayer();
    }

    initSkillLayer() {
        let arr = designManager.instance.getTable(constants.tableName.skill);
        let tmpArr = [];
        for (let i in arr) {
            let row = arr[i];
            if (this.level % 2 == 0) {
                if (row.id == 1 || row.id == 3) {
                    tmpArr.push(row);
                }
                continue;
            }
            if (row.id == 2 || row.id == 4) {
                tmpArr.push(row);
            }
        }
        arr = tmpArr;

        this.skillLayer.getComponent(ItemLayer).initUI(this, arr, this.refreshSkillItem.bind(this));
    }

    refreshSkillItem(itemUI: Node, row: any) {
        let numNode = find("num", itemUI);
        let adNode = find("ad", itemUI);
        let iconNode = find("icon", itemUI);
        let skill = playerModel.instance.getSkillById(row.id);
        iconManager.instance.setSprite(iconNode, row.icon);
        if (skill.num > 0) {
            numNode.active = true;
            adNode.active = false;
            this.setString(numNode, "x" + skill.num);
        } else {
            numNode.active = false;
            adNode.active = true;
        }
    }

    initLocaltext() {
        this.setString(this.levelNode, this.level);
    }

    initEffect() {
        cocosUtil.tweenShake(this.btnAdAtk);
        cocosUtil.tweenShake(this.btnSkip);
    }

    loadLevelLayer() {
        this.initLocaltext();

        this.cloundLayer1.active = false;
        this.cloundLayer2.active = false;
        sdkManager.instance.sendEventLevelStart(this.level);
        levelManager.instance.loadLevel(this.level, () => { }, (err, prefab) => {
            // 关卡UI生成
            for (let i in this.levelLayer.children) {
                this.levelLayer.children[i].destroy();
            }
            let node = instantiate(prefab);
            node.parent = this.levelLayer;
            cocosUtil.setPositionY(node, 0);

            // 设置视图滚动高度
            let listContentTf = this.listContentLayer.getComponent(UITransform);
            let levelTf = node.getComponent(UITransform);
            listContentTf.height = levelTf.height;

            // 从UI中初始化关卡数据
            levelManager.instance.initLevelLayer(this.level, node, this);

            // 初始化玩家
            for (let i in this.playerLayer.children) {
                this.playerLayer.children[i].destroy();
            }
            levelManager.instance.initRolePlayer(this.playerLayer);

            this.listScrollView.scrollToBottom(1);

            // 新手引导
            this.refreshHandLayer();

            // 随机云位置
            this.initCloundLayer();

            this.initSkillLayer();
        });

        if (this.level >= levelManager.instance.shopSecretLevelMin) {
            // 弹出神秘商店
            let obj: any = {};
            obj.type = constants.shopTypes.secret;
            this.openLayer(constants.layers.ShopLayer, obj);
        }
    }

    initCloundLayer() {
        this.cloundLayer1.active = true;
        this.cloundLayer2.active = true;

        let height = this.listContentLayer.getComponent(UITransform).height;
        let gap = 200;
        let maxY = height - gap;
        let minY = gap;
        let midY = (minY + maxY) * 0.5;

        let posY = utilTools.getFloatValue(midY, maxY);
        let clound = this.cloundLayer1.children[0];
        let pos = clound.getPosition();
        pos.y = -posY;
        clound.setPosition(pos);

        posY = utilTools.getFloatValue(minY, midY);
        clound = this.cloundLayer2.children[0];
        pos = clound.getPosition();
        pos.y = -posY;
        clound.setPosition(pos);
    }

    refreshHandLayer() {
        if (this.level != 1 || playerModel.instance.getHandShow()) {
            return;
        }

        if (this.handNode) {
            this.removeHandLayer();
        }

        let floorLayer = levelManager.instance.floorLayerObj[1];
        let firstMonster = floorLayer.children[0].children[0];
        cocosUtil.addHand(firstMonster, this.node, (handNode) => {
            // 根据实际情况再进行微调
            let pos = handNode.getPosition();
            pos.x += 40;
            pos.y -= 10;
            handNode.setPosition(pos);

            handNode["attachNode"] = firstMonster;
            this.handNode = handNode;
        });

    }

    removeHandLayer() {
        this.handNode.destroy();
        this.handNode = null;
    }

    levelRestartRet(data: any) {
        this.loadLevelLayer();
    }

    lifeBackRet(data: any) {
        levelManager.instance.playerBackLife();
    }

    adjustPlayerInCenterRet(data: any) {
        let playerNode = levelManager.instance.playerRoleItem.node;
        let pos = cocosUtil.convertToWorldSpace(playerNode);
        pos = cocosUtil.convertToNodeSpace(this.playerLayer, pos);

        let maxOffset = this.listScrollView.getMaxScrollOffset();

        let playerNodeTf = playerNode.getComponent(UITransform);
        let dy = Math.abs(pos.y) - playerNodeTf.height * (1 - playerNodeTf.anchorY);
        let offsetY = dy - this.listScrollView.node.getComponent(UITransform).height * 0.5;
        if (offsetY < 0) {
            offsetY = 0;
        }
        if (offsetY > maxOffset.y) {
            offsetY = maxOffset.y;
        }
        let offset = this.listScrollView.getScrollOffset();
        if (Math.abs(offset.y - offsetY) <= 50) {
            // 微量移动位置，就不跟随了
            return;
        }
        this.listScrollView.scrollToOffset(v2(0, offsetY), 0.6);

    }

    levelNextRet(data) {
        this.level = playerModel.instance.getLevel();
        this.loadLevelLayer();
    }

    levelEspSuccessRet(data) {
        this.closeLayer();
        let obj: any = {};
        obj.openLevelEspSelectLayer = true;
        this.openLayer(constants.layers.StartLayer, obj);
    };

    skillLayerRefreshRet(data) {
        this.skillLayer.getComponent(ItemLayer).refreshUI();
    }

    judgeLevelSuccessRet(data) {
        levelManager.instance.judgeLevelSuccess();
    }

    showHitEffectRet(data: any) {
        this.hitEffectLayer.getComponent(ItemLayer).addItem(data, this.refreshEffectItem.bind(this));
    }
    refreshEffectItem(itemUI: Node, data: any) {
        let skeleton = itemUI.getComponent(sp.Skeleton);
        skeleton.setAnimation(0, "hit1", false);
        itemUI.setPosition(cocosUtil.convertToNodeSpace(itemUI, data.pos));
        skeleton.setEndListener(() => {
            this.hitEffectLayer.getComponent(ItemLayer).removeItemUIByItemUI(itemUI);
        });
    }

    startFightRet(data: any) {
        this.fightLayer.active = true;
        this.fightLayer.getComponent(FightLayer).loadFightData(data);
        if (this.handNode) {
            this.handNode.active = false;
        }
    }

    fightEndRet(data: any) {
        if (this.handNode) {
            this.handNode.active = true;
        }

        if (!data.isWin) {
            data.name = constants.layers.GameContinueLayer.name;
            data.nextLayerName = constants.layers.FightFailLayer.name;
            eventManager.instance.send(msgac.openLayer, data);
        }
    }

    skillAddRet(data: any) {
        let node = new Node();
        node.addComponent(Sprite);
        let row = designManager.instance.getRowById(constants.tableName.skill, data.skillId);
        iconManager.instance.setSprite(node, row.icon);
        node.parent = this.node;

        let pos = cocosUtil.convertToNodeSpace(node, data.pos);
        node.setPosition(pos);
        node.getComponent(UITransform).width = 100;
        node.getComponent(UITransform).height = 100;
        let itemnUI = this.skillLayer.getComponent(ItemLayer).idItemUIObj[row.id];
        let posTarget = cocosUtil.convertToWorldSpace(itemnUI);
        posTarget = cocosUtil.convertToNodeSpace(node, posTarget);

        tween(node).to(0.5, {
            position: posTarget
        }).call(() => {
            node.destroy();
            this.skillLayer.getComponent(ItemLayer).refreshItemUIById(row.id);
        }).start();
    }

    LevelLayerCloseRet(data: any) {
        this.closeLayer();
    }

    process_event(event: any) {
        let ac = event.ac;
        let data = event.data;
        switch (ac) {
            case msgac.LevelLayerClose:
                this.LevelLayerCloseRet(data);
                break;
            case msgac.skillAdd:
                this.skillAddRet(data);
                break;
            case msgac.fightEnd:
                this.fightEndRet(data);
                break;
            case msgac.startFight:
                this.startFightRet(data);
                break;
            case msgac.showHitEffect:
                this.showHitEffectRet(data);
                break;
            case msgac.judgeLevelSuccess:
                this.judgeLevelSuccessRet(data);
                break;
            case msgac.skillLayerRefresh:
                this.skillLayerRefreshRet(data);
                break;
            case msgac.levelEspSuccess:
                this.levelEspSuccessRet(data);
                break;
            case msgac.levelNext:
                this.levelNextRet(data);
                break;
            case msgac.adjustPlayerInCenter:
                this.adjustPlayerInCenterRet(data);
                break;
            case msgac.lifeBack:
                this.lifeBackRet(data);
                break;
            case msgac.levelRestart:
                this.levelRestartRet(data);
                break;
            default:
                break;
        }
    }

    onButtonClick(node: Node, name: string) {
        if (name.length > 5 && name.substring(0, 5) == "role_") {
            this.onClickRoleItem(node);
            return;
        }
        switch (name) {
            case "skillItem":
                this.onClickSkillItem(node);
                break;
            case "btnAdAtk":
                this.onClickBtnAdAtk(node);
                break;
            case "btnReset":
                this.onClickBtnReset(node);
                break;
            case "btnBack":
                this.onClickBtnBack(node);
                break;
            case "btnSkip":
                this.onClickBtnSkip(node);
                break;
            default:
                break;
        }
    }

    onClickSkillItem(node) {
        if (this["skilling"]) {
            return;
        }
        let skill = playerModel.instance.getSkillById(node.item.id);
        if (skill.num <= 0) {
            let row = designManager.instance.getRowById(constants.tableName.skill, skill.id);
            sdkManager.instance.sendEvent("观看激励视频-获取" + row.name);
            sdkManager.instance.openAd((st: number) => {
                if (st != 1) {
                    return;
                }
                playerModel.instance.addSkillNumById(skill.id);
                this.skillLayer.getComponent(ItemLayer).refreshItemUIByItem(node.item);
                sdkManager.instance.sendEvent("观看完激励视频-获取" + row.name);
            });
            return;
        }
        this["skilling"] = true;
        levelManager.instance.useSkillId(skill.id, this.skillEffectLayer, () => {
            delete this["skilling"];
        });
        this.skillLayer.getComponent(ItemLayer).refreshItemUIByItem(node.item);
    }

    onClickBtnAdAtk(node: Node) {
        sdkManager.instance.sendEvent("观看激励视频-增加10点攻击");
        sdkManager.instance.openAd((st: number) => {
            if (st != 1) {
                return;
            }
            levelManager.instance.addAtk(levelManager.instance.levelAdAtkAddVal);
            sdkManager.instance.sendEvent("观看完激励视频-增加10点攻击");
        });
    }

    onClickBtnSkip(node: Node) {
        sdkManager.instance.sendEvent("观看激励视频-跳关");
        sdkManager.instance.openAd((st: number) => {
            if (st != 1) {
                return;
            }
            levelManager.instance.levelSkip();
            sdkManager.instance.sendEvent("观看完激励视频-跳关");
        });
    }

    onClickBtnReset(node: Node) {
        this.loadLevelLayer();
        sdkManager.instance.addLevelCount();
    }

    onClickRoleItem(node: Node) {
        if (this.handNode && this.handNode["attachNode"] == node) {
            playerModel.instance.setHandShow(1);
            this.removeHandLayer();
        }
        levelManager.instance.onClickRoleItem(node);
    }

    onClickBtnBack(node: Node) {
        this.openLayer(constants.layers.StartLayer);
        this.closeLayer();
    }

}

