class Game extends ManageLang {
    constructor(father, level = "level1") {
        super('Game', father);
        super.addOtherScenes('GamingBoard');
        SPEED_GAME = 1;
        this.level = level;
        this.listPositionRobotInit = [];
        this.scoreText = 0;
    }

    preload() {
        let style = {font: '100px stencil', fill: "#e2e2e2"};
        let text;
        this.load.on('start', () => {
            text = this.add.text(0.5 * WIDTH_WINDOW, 0.5 * HEIGHT_WINDOW, selectWord("LEVEL LOADING ...", "CHARGEMENT DU NIVEAU ..."), style).setOrigin(0.5, 0.5);
            text.alpha = 0.5;
            if (text.displayWidth > WIDTH_WINDOW) {
                text.displayWidth = WIDTH_WINDOW;
                text.scaleY = text.scaleX;
            }
        });
        this.load.on('complete', () => {
            text.destroy();
        });

        if (this.cache.json.exists('level')) {
            this.cache.json.remove('level');
        }
        this.load.json('level', 'public/json/' + this.level + '.json');
        console.log("PRELOAD");

        this.createGamingBoard();
    }

    create() {
        super.create();


        let level = this.cache.json.get('level');
        if (level === undefined) {
            console.log("ERROR : LEVEL UNDEFINED (" + this.level + ")");
            new Button(this, 10, 10, WIDTH_BUTTON, WIDTH_BUTTON, 'back', () => this.clickBack()).setOrigin(0, 0);
            let style = {font: '50px stencil', fill: "#e2e2e2"};
            this.add.text(WIDTH_WINDOW / 2, HEIGHT_WINDOW / 2, selectWord("LEVEL UNDEFINED", "NIVEAU INDEFINI"), style).setOrigin(0.5, 0.5);
            return;
        }

        this.loadSave(level);

        this.doLine = false;

        this.createButtons();

        this.input.keyboard.on('keydown-DELETE', () => {
            this.clickBin();
        });
        this.input.keyboard.on('keydown-E', () => {
            this.clickPencil();
        });
        this.input.keyboard.on('keydown-ENTER', () => {
            this.clickPlus();
        });

        this.setScore(0);
        this.gm.getMyTeam().addEventScore(this.setScore, this);
    }

    update(time, delta) {
        super.update(time, delta);
        if (this.doLine) {
            this.tree.updateLine();
        }
    }

    createGamingBoard() {
        this.gm = new GamingBoard(this);
        if (this.father.scene.getIndex('GamingBoard') !== -1) {
            this.father.scene.remove('GamingBoard');
        }
        this.father.scene.add('GamingBoard', this.gm);
        this.scene.launch('GamingBoard');
        this.gm.pause();
        //this.scene.pause('GamingBoard');
    }

    loadSave(level) {
        this.loadBonus(level.lBonus);
        this.loadTeam(level);
        let myself = [];
        this.gm.getMyTeam().listRobot.forEach(robot => myself.push(robot));
        if (this.listRobot !== undefined) {
            for (let i = 0; i < this.listRobot.length; i++) {
                if (myself[i] !== undefined) {
                    this.listRobot[i].copy(myself[i]);
                }
            }
        } else {
            this.gm.getMyTeam().drawRange();
        }
        this.listRobot = myself;
        if (this.iRobot === undefined) {
            this.iRobot = 0;
        }
        this.setRobotSelected(this.listRobot[this.iRobot], this.iRobot, level, true);

        this.gm.setEnemyRobotVisible(level.enemyVisible);
        this.gm.setBonusVisible(level.bonusVisible);
    }

    setRobotSelected(robot, iRobot = 0, level = this.cache.json.get('level'), force = false) {
        this.iRobot = iRobot;
        let tree;
        if (!force && this.robotSelected !== undefined && this.robotSelected !== robot && this.tree !== undefined && this.initStat !== undefined) {
            this.robotSelected.clearTint();
            this.tree.destroy();
            this.initStat.destroy();
            tree = JSON.parse(robot.getTreeJson());
        } else {
            if (this.initStat !== undefined) {
                this.initStat.destroy();
            }
            if (this.tree !== undefined) {
                tree = JSON.parse(this.tree.getJson(true));
                this.tree.destroy();
            } else {
                tree = JSON.parse(robot.getTreeJson());
            }
        }
        this.tree = this.loadTree(tree);
        this.initStat = this.loadInitSave(level.initStat, robot, robot.damage - DAMAGE_BASE, robot.speedReload - SPEED_RELOAD_BASE, robot.speed - SPEED_BASE, robot.range - RANGE_BASE);

        this.robotSelected = robot;
        if (this.robotSelected.team.listRobot.length > 1) {
            this.robotSelected.setTint(COLOR_SELECTED);
        }
    }

    applyTree() {
        if (this.tree !== undefined && this.robotSelected !== undefined) {
            this.tree.sort();
            this.robotSelected.setNodes(this.tree.getNode());
        }
    }

    loadTree(element, posX = CENTERX_TREE, posY = OFFY_TREE_BEGIN) {
        let tree;
        if (element.x !== undefined && element.y !== undefined) {
            tree = new RectangleNode(element.x, element.y, this, element.type, element.option);
            if (element.lNode !== undefined && element.lNode.length > 0) {
                element.lNode.forEach(rect => tree.addRect(this.loadTree(rect)))
            }
        } else {
            tree = new RectangleNode(posX, posY, this, element.type, element.option);
            if (element.lNode !== undefined && element.lNode.length > 0) {
                let nbRect = element.lNode.length;
                let x = posX - (OFFX_TREE / 2) * (nbRect - 1);
                let y = posY + OFFY_TREE;
                element.lNode.forEach(rect => {
                    tree.addRect(this.loadTree(rect, x, y))
                    x += OFFX_TREE;
                });
            }
        }
        return tree;
    }

    loadInitSave(element, team, ...stat) {
        let height = HEIGHT_BAR;
        let width = height * 7;
        let initStat = new InitStat(this, OFFX_MAP + WIDTH_MAP + 5, OFFY_MAP, width, height, element.valueMax);

        for (let i = 0; i < element.lBar.length; i++) {
            initStat.addBar(stat[i], element.lBar[i].valueMax, element.lBar[i].color, element.lBar[i].lText);
        }

        initStat.lBar[0].addEvent(team.setDamage, team);
        initStat.lBar[1].addEvent(team.setSpeedReload, team);
        initStat.lBar[2].addEvent(team.setSpeed, team);
        initStat.lBar[3].addEvent(team.setRange, team);

        return initStat;
    }

    loadTeam(level) {
        if (level.listTeam !== undefined) {
            let init = 0;
            level.listTeam.forEach(team => {
                init += this.loadT(team.name, team.freeForAll, team.robots, level.robotRandomPosition, init, team.color)
            });
            this.gm.addEventMyTeam(this.setRobotSelected, this);
        }
    }

    loadT(name = MY_TEAM, freeForAll, robots, robotRandomPosition, init = 0, color) {
        let t = new Team(name, freeForAll);
        this.loadRobot(robots, robotRandomPosition, init).forEach(robot => t.addRobot(robot));
        if (color !== undefined) {
            t.getRobots().forEach(robot => robot.setTint(color));
        }
        this.gm.addTeam(t);
        return t.listRobot.length;
    }

    loadRobot(element = [], randomPosition = false, init = 0) {
        let i = init;
        let listRobot = [];
        element.forEach(robot => {
                let lNode = [];
                robot.lNode.forEach(node => {
                    lNode.push(this.loadNode(node))
                });
                if (randomPosition) {
                    if (this.listPositionRobotInit[i] === undefined) {
                        robot.x = Math.random() * ((1 - robot.width / 2) - robot.width / 2) + robot.width / 2;
                        robot.y = Math.random() * ((1 - robot.height / 2) - robot.height / 2) + robot.height / 2;
                        this.listPositionRobotInit[i] = new Position(robot.x, robot.y);
                    } else {
                        robot.x = this.listPositionRobotInit[i].x;
                        robot.y = this.listPositionRobotInit[i].y;
                    }
                }
                listRobot.push(new Robot(WIDTH_MAP * robot.height, WIDTH_MAP * robot.width, WIDTH_MAP * robot.x, WIDTH_MAP * robot.y, this.gm, robot.name, robot.speed, robot.speedReload, robot.range, robot.damage, lNode));
                i += 1;
            }
        )
        return listRobot;
    }

    loadNode(element) {
        let node;
        switch (element.type) {
            case "condition":
                node = new Condition(element.option[0], element.option[1], element.option[2], element.option[3], element.option[4]);
                break;
            case "move":
                node = new Move(element.option[0], element.option[1], element.option[2]);
                break;
            case "attack":
                node = new Attack(element.option[0]);
                break;
            default:
                return;
        }
        if (element.lNode !== undefined) {
            element.lNode.forEach(n => node.addNode(this.loadNode(n)));
        }
        return node;
    }

    loadBonus(element = []) {
        element.forEach(bonus => {
            this.gm.addBonus(this.loadB(bonus));
        })
    }

    loadB(element) {
        let bonus;
        switch (element.style) {
            case "speed":
                bonus = lSpeedBonus[element.number];
                break;
            case "attack":
                bonus = lAttackBonus[element.number];
                break;
            case "shield":
                bonus = lShieldBonus[element.number];
                break;
            default:
                return null;
        }
        return new BonusView(this.gm, element.x * WIDTH_MAP, element.y * WIDTH_MAP, bonus);
    }

    finish() {
        console.log("FINISH");
        let winner;
        if (this.gm.winner()) {
            winner = new Winner(this.father, this, this.score);
        } else {
            winner = new Looser(this.father, this, this.score);
        }
        this.father.scene.add('Finish', winner);

        this.scene.pause('Game');

        this.scene.launch('Finish');

        this.robotSelected = undefined;
    }


    clickNode() {
        this.tryClick();
        this.selected = this.tree.getSelected();

        if (this.selected === undefined)
            return;

        if (this.selected !== this.tree) {
            this.pencilBtn.setVisible(true);
            this.binBtn.setVisible(true);
        }
        if (this.selected.canAddNode) {
            this.plusBtn.setVisible(true);
        }
    }

    doDrag(pointer, target, dragX, dragY) {
        target.setX(dragX);
        target.setY(dragY);
    }

    dragStart() {
        console.log("START DRAG");

        this.doLine = true;
        this.pauseScene();
    }

    dragEnd() {
        console.log("END DRAG");
        this.applyTree();
        this.doLine = false;
    }


    pauseScene() {
        this.playBtn.line = 0;
        this.playBtn.changeFrame(0);

        this.gm.pause();
    }

    resume() {
        this.playBtn.line = 1;
        this.playBtn.changeFrame(0);
        this.gm.resume();
        /*
        this.tryClick();
        this.input.off('pointerdown');
        this.input.on('pointerdown', () => {
            this.selected = this.tree.getSelected();
            this.tryClick();
        });
        this.input.off('drag');
        this.input.off('dragstart');
        this.input.off('dragend');*/
    }

    createButtons() {
        let x = WIDTH_MAP + OFFX_MAP;
        let y = WIDTH_MAP + OFFY_MAP + 5;
        let width = WIDTH_BUTTON;
        let diffX = width * 1.1;
        let line = 0;
        new Button(this, 10, 10, width, width, 'back', () => this.clickBack()).setOrigin(0, 0);
        new Button(this, WIDTH_WINDOW - diffX, HEIGHT_WINDOW, width, width, 'bonusBtn', () => this.clickBonus()).setOrigin(1, 1);
        new Button(this, WIDTH_WINDOW, HEIGHT_WINDOW, width, width, 'save', () => this.clickSave()).setOrigin(1, 1);
        this.playBtn = new Button(this, x, y, width, width, 'play', () => this.clickPlay()).setOrigin(1, 0);
        if (SPEED_GAME === 1) {
            line = 0;
        } else {
            line = 1;
        }
        this.speedBtn = new Button(this, x - diffX, y, width, width, 'speed', () => this.clickSpeed(), line).setOrigin(1, 0);
        this.pencilBtn = new Button(this, x - diffX * 2, y, width, width, 'pencil', () => this.clickPencil(), 0, false).setOrigin(1, 0);
        this.binBtn = new Button(this, x - diffX * 3, y, width, width, 'bin', () => this.clickBin(), 0, false).setOrigin(1, 0);
        this.plusBtn = new Button(this, x - diffX * 4, y, width, width, 'plus', () => this.clickPlus(), 0, false).setOrigin(1, 0);
        if (this.father.sound.mute) {
            line = 1;
        } else {
            line = 0;
        }
        this.muteBtn = new Button(this, x - diffX * 5, y, width, width, 'mute', () => this.clickMute(), line).setOrigin(1, 0);


        let style = {font: (width / 2).toString() + 'px stencil', fill: "#e2e2e2"};
        this.scoreText = this.add.text(OFFX_MAP, y, "SCORE : " + this.scoreText, style).setOrigin(0, 0);

        this.input.on('pointerdown', () => this.clickNode());
        this.input.on('drag', this.doDrag);
        this.input.on('dragstart', () => this.dragStart());
        this.input.on('dragend', () => this.dragEnd());
    }

    setScore(score) {
        this.score = score
        this.scoreText.setText("SCORE : " + this.score);
    }

    clickBonus() {
        this.father.scene.stop('GamingBoard');
        this.father.scene.remove('GamingBoard');
        this.father.scene.add('Description', new Description(this.father, this));

        this.scene.start('Description');
    }

    clickSave() {
        let tree = this.tree.getJson();
        tree = tree.split('{"type":"waria","lNode":[')[1];
        tree = tree.slice(0, -2);
        console.log(tree);

    }

    clickPlay() {
        if (this.gm.paused)
            this.resume();
        else
            this.pauseScene();

        this.playBtn.changeFrame(1);
    }

    clickSpeed() {
        if (SPEED_GAME === 1) {
            SPEED_GAME = 2;
            this.speedBtn.line = 1;
        } else {
            SPEED_GAME = 1;
            this.speedBtn.line = 0;
        }
        this.gm.time.timeScale = SPEED_GAME;
        this.speedBtn.changeFrame(1);
    }

    clickPencil() {
        if (this.selected !== undefined) {
            console.log("PENCIL");
            switch (this.selected.type) {
                case 'attack':
                    this.father.scene.add('AddNode', new AddAttack(this.father, this, this.selected, false));
                    break;
                case 'move':
                    this.father.scene.add('AddNode', new AddMove(this.father, this, this.selected, false));
                    break;
                case 'condition':
                    this.father.scene.add('AddNode', new AddCondition(this.father, this, this.selected, false));
                    break;
                default:
                    return;
            }
            this.scene.pause('Game');
            this.scene.launch('AddNode');
        }
    }

    clickBin() {
        if (this.selected !== undefined) {
            console.log("BIN");
            this.tree.delete(this.selected);

            this.binBtn.changeFrame(0);
            this.tryClick();
            this.applyTree();
        }
    }

    clickPlus() {
        if (this.selected !== undefined && this.selected.canAddNode) {
            console.log("PLUS");

            this.father.scene.add('PlusNode', new PlusNode(this.father, this, this.selected));

            this.scene.launch('PlusNode');

            this.plusBtn.changeFrame(0);

            this.scene.pause('Game');
        }
    }

    clickBack() {
        console.log("BACK");

        this.father.scene.stop('GamingBoard');
        this.father.scene.remove('GamingBoard');
        this.father.scene.stop('Game');
        this.father.scene.start('Type');
    }

    clickMute() {
        console.log("MUTE");
        if (this.father.sound.mute) {
            this.father.sound.mute = false;
            this.muteBtn.line = 0
        } else {
            this.father.sound.mute = true;
            this.muteBtn.line = 1;
        }
        this.muteBtn.changeFrame(1);
    }

    tryClick() {
        this.pencilBtn.setVisible(false);
        this.binBtn.setVisible(false);
        this.plusBtn.setVisible(false);
        if (this.selected != undefined) {
            this.selected.deselect();
            this.selected = undefined;
        }
    }

    setLevel(level) {
        if (this.level !== level) {
            this.level = level;
            this.listPositionRobotInit = [];
            this.robotSelected = undefined;
        }
        console.log(this.level);
    }
}