// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import Game, { FISH_OUT, GAME_STATE, Option } from "../tool/Game";
import pg from "../tool/pg";

const { ccclass, property } = cc._decorator;

export function getDegree(p1, p2) {
    let vector = p2.sub(p1);
    let degree = Math.atan(vector.y / vector.x) / Math.PI * 180;
    if (vector.x >= 0) {
        if (vector.y < 0) {
            degree += 360;
        }
    } else {
        if (vector.y > 0) {
            degree += 180;
        } else {
            degree = 180 + degree;
        }
    }
    return -(-degree + 90);//角度计算方法
}
@ccclass
export default class NewClass extends cc.Component {
    @property(cc.Node)
    res: cc.Node = null;
    @property(cc.Node)
    layout_player: cc.Node = null;
    @property(cc.Node)
    layout_robot: cc.Node = null;

    @property(cc.Node)
    item_left: cc.Node = null;
    @property(cc.Node)
    item_right: cc.Node = null;

    onLoad() {
        pg.event.on("game_start", () => {
            this.gameStart();
        })
    }

    private count: number;
    private list: Option[];
    private fishs: cc.Node[];
    gameStart() {
        //游戏开始。允许出鱼
        let page = Game.getIns().getCurrentPage();
        let list = page.optionList.concat();
        list = JSON.parse(JSON.stringify(list));
        list.sort((A, B) => { return Math.random() < 0.5 });
        this.list = list;
        this.count = 0;
        this.lastCount = null;
        this.robotFishTime = null;
        this.fishs = [];
        this.viewFishs = [];
        this.touchFishs = [];
        //根据顺序生成对应的鱼。
        //顺序根据时间来进行跳动。当顺序跳动之后，就会产生新的鱼。
    }
    private lastCount: number;
    private viewFishs: Option[];
    private touchFishs: Option[];
    getFishByCount(count) {
        if (count <= this.lastCount) return null;
        if (!this.list) return;
        if (this.list.length == this.touchFishs.length) {
            Game.getIns().state = GAME_STATE.OVER;
            return pg.event.emit("game_time_over");
        }
        this.lastCount = count;
        let list = this.list.filter((li) => {
            return this.viewFishs.every(v => v.id != li.id) && this.touchFishs.every(t => t.id != li.id);
        });
        if (list.length == 0) return null;
        let data = JSON.parse(JSON.stringify(list[count % list.length]));
        data.fish.isLeft = Math.random() < 0.5;
        let item_base = data.fish.isLeft ? this.item_left : this.item_right;
        let item = cc.instantiate(item_base);
        this.updateFish(item, data);
        this.viewFishs.push(data);
        return item;
    }
    private fishCount: number;
    private lastY: number;
    updateFish(item, data: Option) {
        pg.view.touchOn(item, this.onTouchItem, this);
        if (!this.fishCount) this.fishCount = 0;
        let id = this.fishCount % 5 + 1;
        this.fishCount++;
        pg.view.visible(pg.view.find(item, 'fish/icon_fish1'), id == 1);
        pg.view.visible(pg.view.find(item, 'fish/icon_fish2'), id == 2);
        pg.view.visible(pg.view.find(item, 'fish/icon_fish3'), id == 3);
        pg.view.visible(pg.view.find(item, 'fish/icon_fish4'), id == 4);
        pg.view.visible(pg.view.find(item, 'fish/icon_fish5'), id == 5);

        item.parent = this.node;
        item.data = data;
        data.fish.node = item;
        //渲染部分
        if (data.type == "txt") {
            pg.view.visible(pg.view.find(item, 'layout_text'), true);
            pg.view.visible(pg.view.find(item, 'layout_img'), false);
            pg.view.setString(pg.view.find(item, "layout_text/text"), data.txt);
        } else {
            pg.view.visible(pg.view.find(item, 'layout_text'), false);
            pg.view.visible(pg.view.find(item, 'layout_img'), true);
            pg.view.setNetImg(pg.view.find(item, 'layout_img/img'), data.picUrl, { w: 118, h: 110 })
        }
        //x y   起始点 和终点  进行  随机
        cc.Tween.stopAllByTarget(item);
        if (data.fish.isLeft) {
            //左往右
            item.x = -(1334 / 2 + Math.random() * 200)
            item.y = -290 + Math.random() * 400;//
            cc.tween(item).to(10 + Math.random() * 10, { x: 1500 }).call(() => {
                data.fish.isOut = FISH_OUT.OUT;
                this.viewFishs = this.viewFishs.filter(v => v.id != data.id);
            }).start();
        } else {
            //右往左
            item.x = (1334 / 2) + Math.random() * 200;
            item.y = -290 + Math.random() * 400;
            cc.tween(item).to(10 + Math.random() * 10, { x: -1500 }).call(() => {
                data.fish.isOut = FISH_OUT.OUT;
                this.viewFishs = this.viewFishs.filter(v => v.id != data.id);
            }).start();
        }
    }
    private touching: boolean;

    fishingRight(item, layout, data: Option) {
        return new Promise((resolve, reject) => {
            let wave = pg.view.find(layout, 'wave')
            wave.active = true;
            wave.angle = getDegree(cc.v2(item), cc.v2(layout).add(cc.v2(wave)));
            let text = pg.view.find(layout, "text");
            text.active = true;
            data.audioUrl && pg.audio.playAudioByUrl(data.audioUrl)
            cc.tween(item)
                .to(1, { x: layout.x, y: layout.y + wave.y, scaleX: item.scaleX * 0.1, scaleY: item.scaleY * 0.1 }).call(() => {
                    //处理内容
                    data.fish.isOut = FISH_OUT.OUT;
                    wave.active = false;
                    text.active = false;
                    this.touching = false;
                    resolve('');
                }).start();
        });
    }
    fishingError(item, layout, data) {
        return new Promise((resolve, reject) => {
            pg.audio.playLocalAudio(pg.view.find(this.res, "audio/error"))
            if (data.fish.isLeft) {
                //左往右
                cc.tween(item).to(3, { x: 1500 }).call(() => {
                    data.fish.isOut = FISH_OUT.OUT;
                    item.active = false;
                    setTimeout(() => { item.parent = null; }, 1000);
                    if (this.touchFishs.every(fish => fish.id != data.id)) {
                        resolve('');
                    }
                }).start();
            } else {
                //右往左
                cc.tween(item).to(3, { x: -1500 }).call(() => {
                    data.fish.isOut = FISH_OUT.OUT;
                    item.active = false;
                    setTimeout(() => { item.parent = null; }, 1000);
                    if (this.touchFishs.every(fish => fish.id != data.id)) {
                        resolve('');
                    }
                }).start();
            }
            setTimeout(() => { this.touching = false; }, 500);
        });
    }
    fishing(item, layout) {
        return new Promise(async (resolve, reject) => {
            let data = item.data;
            //item停止动画并
            cc.Tween.stopAllByTarget(item);
            if (data.right) {
                await this.fishingRight(item, layout, data);
            } else {
                await this.fishingError(item, layout, data);
            }
            this.touchFishs.push(data);
            return resolve(data.right);
        });
    }
    //开始点击     点击角色
    async onTouchItem(e) {
        if (this.touching) return;
        this.touching = true;
        let item = e.target;
        let data = item.data;
        if (this.touchFishs.some(fish => fish.id == data.id)) return;
        if (data.fish.isOut != FISH_OUT.RUNNING) return;
        data.fish.isOut = FISH_OUT.TOUCH;
        let isRight = await this.fishing(item, this.layout_player);
        isRight && Game.getIns().player.addScore();
        !isRight && Game.getIns().player.addError();
    }
    //机器人随机钓鱼
    private robotFishTime;
    async onRobotFishing() {
        this.layout_robot.active = !Game.getIns().singleGame;
        if (!this.viewFishs) return;
        if (Game.getIns().singleGame) return;
        let nowTime = new Date().getTime();
        if (!this.robotFishTime) this.robotFishTime = nowTime;
        let time = 5000;//level来确定触发捕鱼的间隔时间。
        if (nowTime - this.robotFishTime > time) {
            let datas = this.viewFishs.filter(dat => dat.fish.node.x > -1334 / 2 && dat.fish.node.x < 1334 / 2);
            let data = datas[Math.floor(Math.random() * datas.length)];
            if (data.fish.isOut != FISH_OUT.RUNNING) return;
            if (this.touchFishs.some(fish => fish.id == data.id)) return;
            this.robotFishTime = nowTime - 1000;//-1000 动画时间
            if (!data.right) return;
            data.fish.isOut = FISH_OUT.TOUCH;
            let isRight = await this.fishing(data.fish.node, this.layout_robot);
            isRight && Game.getIns().robot.addScore();
            !isRight && Game.getIns().player.addError();
        }
    }

    get fishLen() {
        if (!this.fishs) return 999;
        let arr = this.fishs.filter(item => {
            let data: Option = item.data;
            return data.fish.isOut == FISH_OUT.RUNNING;
        })
        this.fishs = arr;
        return this.fishs.length;
    }
    update(dt) {
        if (Game.getIns().state != GAME_STATE.RUNNING) return;
        if (this.fishLen < 5) this.count++;
        this.onRobotFishing();
        let fish = this.getFishByCount(this.count);
        if (fish) this.fishs.push(fish);
    }
}
