import { Component, instantiate, Node, Prefab, tween, Tween, Vec3 } from "cc";
import { BaseLayer } from "../../common/BaseLayer";
import { cocosUtil } from "../../utils/cocosUtil";
import { utilTools } from "../../utils/utilTools";
import { constants } from "../data/constants";
import { localText } from "../data/localText";
import { msgac } from "../data/msgac";
import { RoleItem } from "../item/RoleItem";
import { playerModel } from "../model/playerModel";
import { audioManager } from "./audioManager";
import { designManager } from "./designManager";
import { eventManager } from "./eventManager";
import { resManager } from "./resManager";
import { sdkManager } from "./sdkManager";
import { skillManager } from "./skillManager";

export class levelManager {
    private static _instance: levelManager;
    private constructor() { }
    public static get instance(): levelManager {
        if (!this._instance) {
            this._instance = new levelManager();
        }
        return this._instance;
    }

    // 关卡内容节点
    levelContentLayer: Node;
    levelLayerComponent: Component;

    // {floor层数:floorLayer节点}
    floorLayerObj: any = {};

    // 玩家对象
    playerRoleItem: RoleItem;

    // 当前正在打的关卡id
    level: number = 0;
    // 当前关卡是否有BOSS
    levelBoss: boolean = false;
    // BOSS宝箱是否已拾取
    bossBoxHasGet: boolean = false;
    // 关卡是否已胜利，并且弹出狩猎成功界面
    isSuccess: boolean = false;
    // 是否是跳关胜利
    isSkip: boolean = false;

    // 普通关卡的数量
    levelMax: number = 20;
    // 特殊关卡id数组
    levelEspIdArr: number[] = [-1, -2, -3, -4];

    // 商店广告增加金币数量
    shopAdCoin: number = 500;
    // 开局神秘商店最小关卡
    shopSecretLevelMin: number = 2;
    // 观看广告直接加的战力值
    levelAdAtkAddVal: number = 10;
    // 金币广告界面增加金币数量
    adCoinNum: number = 500;

    // 装备武器id
    equipWeaponId: number = 0;
    // 装备衣服id
    equipDressId: number = 0;

    // 行动之前的位置
    playerLastPos: Vec3;
    playerLastGround: Node;

    // 防止重复点击
    canClickGoOn: boolean = true;

    onClickRoleItem(clickRoleNode: Node) {
        if (this.playerRoleItem.bodySkeleton.animation != constants.animations.standBy) {
            return;
        }

        let playerNode = this.playerRoleItem.node;
        let clickRoleItem = clickRoleNode.getComponent(RoleItem);
        if (clickRoleItem.isPlayer()) {
            return;
        }

        if (!this.canClickGoOn) {
            return;
        }

        clickRoleItem.closeHand();

        if (clickRoleItem.hasAd()) {
            sdkManager.instance.openAd((st: number) => {
                if (st != 1) {
                    return;
                }
                clickRoleItem.hideAd();
                this.onClickRoleItem(clickRoleNode);
            });
            return;
        }

        this.canClickGoOn = false;

        let posTarget = cocosUtil.convertToNodeSpace(playerNode, clickRoleItem.getPlayerWorldPos(playerNode));

        if (!this.isNeedPlayerMove(clickRoleItem)) {
            // 不用移动过去
            this.moveToClickRoleEnd(clickRoleNode);
            return;
        }

        this.playerLastPos = playerNode.getPosition();
        this.playerLastGround = this.playerRoleItem.groundNode;

        if (this.playerRoleItem.groundNode == clickRoleItem.groundNode) {
            // 同一个地板
            if (playerNode.position.x == posTarget.x && playerNode.position.y == posTarget.y) {
                // 已在目标位置上
                this.moveToClickRoleEnd(clickRoleNode);
            } else {
                // 移动过去
                if (playerNode.getPosition().x <= posTarget.x) {
                    this.playerRoleItem.setBodyScale(constants.playerBodyScale, constants.playerBodyScale);
                } else {
                    this.playerRoleItem.setBodyScale(-constants.playerBodyScale, constants.playerBodyScale);
                }
                this.playerRoleItem.playAnimation(constants.animations.walk, true);
                let time = Math.abs(playerNode.getPosition().x - posTarget.x) / constants.playerWalkSpeed;
                tween(playerNode).to(time, {
                    position: posTarget
                }).call(() => {
                    this.moveToClickRoleEnd(clickRoleNode);
                }).start();
            }
            return;
        }

        // 不同地板，闪现过去
        this.playerRoleItem.startOpenPortal(() => {
            let bodyNode = this.playerRoleItem.bodyNode;
            Tween.stopAllByTarget(bodyNode);
            if (clickRoleItem.isBodyScalePositive()) {
                bodyNode.setScale(constants.playerBodyScale, constants.playerBodyScale);
            } else {
                bodyNode.setScale(-constants.playerBodyScale, constants.playerBodyScale);
            }
            playerNode.setPosition(posTarget);
            this.playerRoleItem.playerAppearFromPortal(() => {
                this.moveToClickRoleEnd(clickRoleNode);
            });
        });

    }

    moveToClickRoleEnd(clickRoleNode: Node) {
        let playerNode = this.playerRoleItem.node;
        let clickRoleItem = clickRoleNode.getComponent(RoleItem);
        if (this.isNeedPlayerMove(clickRoleItem)) {
            this.playerRoleItem.floor = clickRoleItem.floor;
            this.playerRoleItem.groundNode = clickRoleItem.groundNode;
        }
        this.playerRoleItem.playAnimation(constants.animations.standBy, true);

        if (clickRoleItem.isBodyScalePositive()) {
            this.playerRoleItem.setBodyScale(constants.playerBodyScale, constants.playerBodyScale);
        } else {
            this.playerRoleItem.setBodyScale(-constants.playerBodyScale, constants.playerBodyScale);
        }

        if (clickRoleItem.roleType == constants.roleItemTypes.monster) {
            let obj: any = {};
            obj.monsterRoleItem = clickRoleItem;
            eventManager.instance.send(msgac.startFight, obj);
            return;
        }

        if (this.isNeedPlayerMove(clickRoleItem)) {
            // 镜头跟随
            eventManager.instance.send(msgac.adjustPlayerInCenter);
        }


        if (clickRoleItem.roleType == constants.roleItemTypes.coinBox) {
            // 金币宝箱
            clickRoleItem.openBoxAward(() => {
                this.canClickGoOn = true;
                clickRoleNode.destroy();
                let info: any = {};
                info.name = constants.layers.AwardGetLayer.name;
                info.coin = clickRoleItem.coin;
                info.isBoss = clickRoleItem.isBoss;
                info.isBox = true;
                eventManager.instance.send(msgac.openLayer, info);
            });
            return;
        }

        if (clickRoleItem.roleType == constants.roleItemTypes.shop) {
            // 商店
            this.canClickGoOn = true;
            clickRoleNode.destroy();
            let info: any = {};
            info.name = constants.layers.ShopLayer.name;
            info.type = clickRoleItem.roleTypeP1;
            info.id = clickRoleItem.roleTypeP2;
            eventManager.instance.send(msgac.openLayer, info);
            return;
        }

        if (clickRoleItem.roleType == constants.roleItemTypes.arrow) {
            // 弓箭
            clickRoleItem.playAnimation(constants.animations.animation, false);
            clickRoleItem.shootArrows(() => {
                this.canClickGoOn = true;
            });
            return;
        }

        if (clickRoleItem.roleType == constants.roleItemTypes.atk) {
            // 战力倍增
            this.canClickGoOn = true;
            clickRoleNode.destroy();
            let atkAddVal = 0;
            switch (clickRoleItem.roleTypeP1) {
                case constants.atkChangeTypes.add:
                    atkAddVal = clickRoleItem.atk;
                    break;
                case constants.atkChangeTypes.multi:
                    atkAddVal = (clickRoleItem.atk - 1) * this.playerRoleItem.atk;
                    break;
                default:
                    break;
            }
            if (atkAddVal > 0) {
                this.playerRoleItem.addAtk(atkAddVal);
            }
            return;
        }

        if (clickRoleItem.roleType == constants.roleItemTypes.equip) {
            // 增加战力
            this.canClickGoOn = true;
            clickRoleNode.destroy();
            this.playerRoleItem.addAtk(clickRoleItem.atk);
            this.addEquip(clickRoleItem.getEquipId());
            return;
        }

        if (clickRoleItem.roleType == constants.roleItemTypes.skill) {
            // 获得技能
            this.canClickGoOn = true;
            clickRoleNode.destroy();
            playerModel.instance.addSkillNumById(clickRoleItem.roleTypeP1, clickRoleItem.atk);

            let info: any = {};
            info.skillId = clickRoleItem.roleTypeP1;
            info.num = clickRoleItem.atk;
            info.pos = cocosUtil.convertToWorldSpace(clickRoleNode);
            eventManager.instance.send(msgac.skillAdd, info);
            return;
        }

        if (clickRoleItem.roleType == constants.roleItemTypes.dapao) {
            // 大炮
            clickRoleItem.playAnimation(constants.animations.attack, false);
            clickRoleItem.shootBullets(() => {
                this.canClickGoOn = true;
            });
            return;
        }

        if (clickRoleItem.roleType == constants.roleItemTypes.gunshi) {
            // 滚石
            clickRoleItem.playAnimation(constants.animations.animation, true);
            clickRoleItem.startGunShi(() => {
                this.canClickGoOn = true;
            });
            return;
        }

        this.canClickGoOn = true;
        eventManager.instance.send(msgac.showNotice, "未实现的功能");
    }

    // 添加受击特效
    addHitEffect(node: Node) {
        let obj: any = {};
        obj.pos = cocosUtil.convertToWorldSpace(node, true);
        eventManager.instance.send(msgac.showHitEffect, obj);
    }

    // 判断一下如果敌人全部阵亡，则弹出狩猎成功的界面，只会弹一次
    judgeLevelSuccess() {
        if (this.isSuccess) {
            return;
        }

        for (let i in this.floorLayerObj) {
            let floorLayer = this.floorLayerObj[i];
            let arr = this.getAllMonsterByFloorLayer(floorLayer);
            for (let j in arr) {
                let roleItem = arr[j];
                if (!roleItem.isDead()) {
                    // 还有怪物存活，直接返回还未通关
                    return;
                }
            }
        }

        if (this.levelBoss && !this.bossBoxHasGet) {
            // 还未拾取BOSS宝箱
            return;
        }

        this.isSuccess = true;

        let obj: any = {};
        obj.name = constants.layers.GameContinueLayer.name;
        obj.nextLayerName = constants.layers.LevelSuccessLayer.name;
        eventManager.instance.send(msgac.openLayer, obj);
    }

    // 刷新玩家形象
    refreshPlayerBody() {
        this.playerRoleItem.bodySkeleton.setSkin(this.getSkinName(this.equipWeaponId, this.equipDressId));
    }

    getSkinName(weaponId: number, dressId: number) {
        let skinName = "";
        if (dressId > 0) {
            let dressRow = designManager.instance.getRowById(constants.tableName.equip, dressId);
            skinName = dressRow.skin;
        } else {
            skinName = "r1";
        }
        if (weaponId > 0) {
            let weaponRow = designManager.instance.getRowById(constants.tableName.equip, weaponId);
            skinName += weaponRow.skin;
        } else {
            skinName += "w1";
        }

        return skinName;
    }

    // 释放技能
    useSkillId(id: number, skillEffectLayer: Node, cb?: Function) {
        let skill = playerModel.instance.getSkillById(id);
        let row = designManager.instance.getRowById(constants.tableName.skill, id);
        if (skill.num <= 0 || !row) {
            if (cb) {
                cb();
            }
            return;
        }

        // 减少怪物战力
        let targetArr = [];
        let range = 2;
        let floorStart = this.playerRoleItem.floor - range;
        if (floorStart < 1) {
            floorStart = 1;
        }
        let floorEnd = this.playerRoleItem.floor + range;
        for (let i = floorStart; i <= floorEnd; i++) {
            let floorLayer = this.floorLayerObj[i];
            if (!floorLayer) {
                continue;
            }
            let arr = this.getAllMonsterByFloorLayer(floorLayer);
            targetArr = targetArr.concat(arr);
        }
        if (targetArr.length <= 0) {
            if (cb) {
                cb();
            }
            eventManager.instance.send(msgac.showNotice, localText.textObj.noMonster);
            return;
        }

        // 播放音效
        audioManager.instance.playEffect(row.sound);
        playerModel.instance.subSkillNumById(id);

        let tmpArr = [];
        if (row.target > 0) {
            let num = row.target;
            while (num > 0) {
                num--;
                let index = Math.floor(Math.random() * targetArr.length);
                tmpArr.push(targetArr[index]);
                targetArr.splice(index, 1);
                if (targetArr.length <= 0) {
                    break;
                }
            }
        } else {
            tmpArr = targetArr;
        }
        // 统计玩家需要增加的战力
        let roleAtkAdd = 0;
        for (let i in tmpArr) {
            let roleItem = tmpArr[i];
            let add = row.atk;
            if (row.atk > roleItem.atk) {
                add = roleItem.atk;
            }
            roleAtkAdd += add;

            // 不同技能特效，位置和受击时间点不一样
            let pos = cocosUtil.convertToWorldSpace(roleItem.node);
            let delay = 0;
            switch (row.body) {
                case "yunshi":
                    delay = 0.5;
                    pos.y += 40;
                    break;
                case "ljf":
                    pos.y += 10;
                    break;
                case "sd":
                    pos.y += 40;
                    break;
                default:
                    break;
            }
            this.levelLayerComponent.scheduleOnce(() => {
                if (roleAtkAdd > 0) {
                    this.addAtk(roleAtkAdd);
                    roleAtkAdd = 0;
                }
                roleItem.addAtk(-row.atk);
                // 受击动画
                roleItem.playAnimation(constants.animations.hit, false, () => {
                    roleItem.playAnimation(constants.animations.standBy, true);
                });
            }, delay);

            // 显示技能特效
            skillManager.instance.showSkillEffect(id, pos, skillEffectLayer, cb);

        }
    }

    // 跳过当前关卡
    levelSkip() {
        // 所有怪物播放死亡动画
        this.isSkip = true;
        let chs = this.levelContentLayer.children;
        for (let i in chs) {
            let floorLayer = chs[i];
            let arr = this.getAllMonsterByFloorLayer(floorLayer);
            for (let j in arr) {
                let roleItem = arr[j];
                roleItem.showDeadEffect();
            }
        }
    }

    getAllMonsterByFloorLayer(floorLayer: Node) {
        let arr = [];
        let groundNodeArr = floorLayer.children;
        for (let i in groundNodeArr) {
            let groundNode = groundNodeArr[i];
            let roles = groundNode.children;
            for (let tmp in roles) {
                let roleNode = roles[tmp];
                let roleItem = roleNode.getComponent(RoleItem);
                if (!roleItem || roleItem.roleType != constants.roleItemTypes.monster) {
                    continue;
                }
                if (roleItem.isDead()) {
                    continue;
                }
                arr.push(roleItem);
            }
        }

        return arr;
    }

    isNeedPlayerMove(clickRoleItem: RoleItem) {
        if (clickRoleItem.roleType == constants.roleItemTypes.arrow
            || clickRoleItem.roleType == constants.roleItemTypes.dapao
            || clickRoleItem.roleType == constants.roleItemTypes.gunshi
        ) {
            // 弓箭，大炮，滚石 不用移动过去
            return false;
        }
        return true;
    }

    /**
     * 获得装备
     * 低等级不要覆盖掉高等级装备皮肤
     * @param id 装备id 
     */
    addEquip(id: number) {
        let row = designManager.instance.getRowById(constants.tableName.equip, id);
        let nowLv = 0;
        if (row.type == constants.equipTypes.weapon) {
            if (this.equipWeaponId > 0) {
                nowLv = designManager.instance.getRowById(constants.tableName.equip, this.equipWeaponId).lv;
            }
            if (row.lv > nowLv) {
                this.equipWeaponId = id;
                // 玩家形象变化
                this.refreshPlayerBody();
            }
        } else if (row.type == constants.equipTypes.dress) {
            if (this.equipDressId > 0) {
                nowLv = designManager.instance.getRowById(constants.tableName.equip, this.equipDressId).lv;
            }
            if (row.lv > nowLv) {
                this.equipDressId = id;
                // 玩家形象变化
                this.refreshPlayerBody();
            }
        }
    }

    // 玩家战力增加
    addAtk(val: number) {
        this.playerRoleItem.addAtk(val);
    }

    // 通关后要处理的数据
    levelSuccess() {
        if (!this.isLevelEsp()) {
            playerModel.instance.setLevel(this.level + 1);
            this.loadLevelNext();
        }
    }

    // 计算下一关卡，特殊关卡不作处理
    loadLevelNext() {
        if (this.isLevelEsp()) {
            return -1;
        }
        let next = this.level + 1;

        if (next > this.levelMax) {
            // 超过最大关卡数量，随机之前的老关卡
            if (next % 10 == 0) {
                // boss关卡
                let num = Math.floor(this.levelMax / 10);
                let random = Math.floor(Math.random() * num) + 1;
                next = random * 10;
            } else {
                // 普通关卡
                let arr = [];
                for (let i = 1; i <= this.levelMax; i++) {
                    if (i % 10 == 0) {
                        continue;
                    }
                    arr.push(i);
                }
                next = utilTools.getRandomItemByArr(arr);
            }
            console.log("load random next level:" + next);
        }
        console.log("load next level:" + next);
        playerModel.instance.setLevelAct(next);
        this.loadLevel(next);

        return next;
    }

    // 是否是特殊关卡
    isLevelEsp() {
        if (this.level < 0) {
            return true;
        }
        return false;
    }

    // 是否已打到最大关卡
    isLevelMax() {
        if (playerModel.instance.getLevel() >= this.levelMax) {
            return true;
        }
        return false;
    }

    /**
     * 获取通关后奖励金币数量
     * 每10关为boss关卡，奖励比较多
     * 特殊关卡奖励另算
     */
    getLevelSuccessCoin() {
        if (this.isLevelEsp()) {
            return 1000;
        }
        if (this.level % 10 == 0) {
            return 500;
        }
        return 200;
    }

    playerBackLife() {
        if (this.playerLastPos) {
            this.playerRoleItem.node.setPosition(this.playerLastPos);
        }
        if (this.playerLastGround) {
            this.playerRoleItem.groundNode = this.playerLastGround;
        }
        eventManager.instance.send(msgac.adjustPlayerInCenter);
        this.playerRoleItem.dead = false;
        this.playerRoleItem.playerAppearFromPortal(() => {
            this.playerRoleItem.playAnimation(constants.animations.standBy, true);
        });
    }

    loadLevel(level: number, onProgress?: Function, onComplete?: Function) {
        if (level > 0) {
            // 常规关卡
            if (level > this.levelMax) {
                level = playerModel.instance.getLevelAct();
            }
        }
        let path = constants.bundles.common.dir.level + "/" + constants.level + level;
        console.log("load level data:" + level);
        resManager.instance.loadAsset(constants.bundles.common.name, path, Prefab, onProgress, onComplete);
    }

    initLevelLayer(level: number, node: Node, levelLayer: BaseLayer) {
        this.levelLayerComponent = levelLayer;
        this.level = level;
        this.playerRoleItem = null;
        this.levelContentLayer = node;
        this.equipWeaponId = playerModel.instance.getEquipWeaponId();
        this.equipDressId = playerModel.instance.getEquipDressId();
        this.playerLastGround = null;
        this.playerLastPos = null;
        this.floorLayerObj = {};
        this.levelBoss = false;
        this.bossBoxHasGet = false;
        this.isSuccess = false;
        this.canClickGoOn = true;
        this.isSkip = false;

        let floorArr = node.children;
        let length = floorArr.length;
        let floor = 0;
        for (let i = length - 1; i >= 0; i--) {
            floor++;
            let floorLayer = floorArr[i];
            let groundNodeArr = floorLayer.children;
            this.floorLayerObj[floor] = floorLayer;

            for (let j in groundNodeArr) {
                let groundNode = groundNodeArr[j];
                let roles = groundNode.children;
                for (let tmp in roles) {
                    let roleNode = roles[tmp];
                    let roleItem = roleNode.getComponent(RoleItem);
                    if (!roleItem) {
                        continue;
                    }
                    if (roleItem.isPlayer()) {
                        // 玩家
                        this.playerRoleItem = roleItem;
                        this.playerRoleItem.roleTypeP1 = playerModel.instance.getRoleId();
                        // 暂时不管表里的配置，初始战力以关卡配置为准
                        // let roleRow = designManager.instance.getRowById(constants.tableName.role, playerModel.instance.getRoleId());
                        // this.playerRoleItem.atk = roleRow.atk;
                        // this.playerRoleItem.setAtkVal(roleRow.atk);
                    }
                    roleItem.init(groundNode, floor, levelLayer);
                    if (roleItem.roleType == constants.roleItemTypes.monster && roleItem.isBoss) {
                        this.levelBoss = true;
                    }
                }

            }
        }

    }

    initRolePlayer(parent: Node) {
        let pos = cocosUtil.convertToWorldSpace(this.playerRoleItem.node);
        this.playerRoleItem.node.parent = parent;
        pos = cocosUtil.convertToNodeSpace(this.playerRoleItem.node, pos);
        this.playerRoleItem.node.setPosition(pos);
        this.playerRoleItem.setAtkVal();
        this.refreshPlayerBody();
    }

}

