const Phaser = require('phaser');
const Node = require('./zone.node');
const ZoneControls = require('./zone.controls');
const { POSITIONS: { MENU_MAIN }, TEXT } = require('./constants');

const X = MENU_MAIN.x();
const Y = MENU_MAIN.y();
const WIDTH = MENU_MAIN.width();
const HEIGHT = MENU_MAIN.height();


// Mouse click hold to move, Q + E to zoom in and out
// Press 'A' to reset allocated passive nodes

class Zones extends Phaser.Scene {
    constructor() {
        super({ key: 'Zones' });
    }

    preload() {
        this.load.image('eye', 'https://labs.phaser.io/assets/particles/green-orb.png');
    }

    create(zone) {
        if (!zone) return false;
        if (!this.scene.get('ZoneControls')) this.scene.manager.add('ZoneControls', ZoneControls, true, zone.id);
        this.graphics = this.add.graphics();
        this.cameras.main.setViewport(X, Y, WIDTH, HEIGHT);
        this.addNodes(zone.graph.nodes);
        this.drawEdges(zone.graph.edges);
        this.addCameraControl();
        this.addEvents(zone.id);
        return this;
    }

    addNodes(nodeData) {
        this.nodes = [];
        nodeData.forEach((n, i) => {
            this.nodes[i] = this.add.existing(
                new Node(this, n.x * 50 + 200, n.y * 50 + 200, i, n.success, n.tag)
            ).setInteractive();
        });
    }

    addCameraControl() {
        this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl({
            camera: this.cameras.main,
            zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
            zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E),
            acceleration: 0.005,
            drag: 0.0005,
            maxSpeed: 0.001,
        });
    }

    addEvents(zoneId) {
        this.input.on('pointerover', (pointer, gameObjects) => {
            if (gameObjects[0] instanceof Node) {
                this.displayNodeText(gameObjects[0], pointer);
            }
        });
        this.input.on('pointerout', (pointer, gameObjects) => {
            if (gameObjects[0] instanceof Node) {
                this.nodeText.destroy();
            }
        });
        this.input.on('pointerup', (pointer, gameObjects) => {
            if (Math.abs(pointer.upX - pointer.downX) < 5
                    && Math.abs(pointer.upY - pointer.downY) < 5) {
                // Check cursor hasn't significantly moved during point allocation
                // If panning and mouse release is on node it won't allocate
                if (gameObjects[0] instanceof Node) {
                    const team = this.registry.get('cryps').filter(c => c.active).map(c => c.id);
                    if (gameObjects[0].success) return false;
                    this.registry.get('ws').sendZoneJoin(zoneId, gameObjects[0].id, team);
                }
            }
            return true;
        });
        this.input.on('pointermove', (pointer) => {
            const zoomFactor = 2 / this.cameras.main.zoom;
            if (this.registry.get('pan')) {
                const points = pointer.getInterpolatedPosition(2);
                this.cameras.main.scrollX -= zoomFactor * (points[1].x - points[0].x);
                this.cameras.main.scrollY -= zoomFactor * (points[1].y - points[0].y);
            }
        }, this);
    }

    drawEdges(edgeData) {
        this.graphics.clear();
        edgeData.forEach((e) => {
            const nodeA = this.nodes[e[0]];
            const nodeB = this.nodes[e[1]];
            if (nodeA.success && nodeB.success) {
                this.graphics.lineStyle(10, 0xfff00f, 0.2);
            } else {
                this.graphics.lineStyle(2, 0xffffff, 0.2);
            }
            this.graphics.lineBetween(nodeA.x, nodeA.y, nodeB.x, nodeB.y);
            return true;
        });
    }

    displayNodeText(node, pointer) {
        if (this.nodeText) this.nodeText.destroy();
        this.nodeText = this.add.text(node.x, node.y, node.text, TEXT.HOVER).setPadding(32);
        this.nodeText.setAlpha(0.8);
        this.nodeText.setOrigin(pointer.x >= WIDTH * 0.65 ? 1 : 0,
            pointer.y >= HEIGHT * 0.25 ? 1 : 0);
        this.nodeText.setWordWrapWidth(450);
        this.nodeText.setScale(1 / this.cameras.main.zoom);
    }

    camPan(bool) {
        this.pan = bool;
    }

    update(delta) {
        this.controls.update(delta);
    }

    cleanUp() {
        if (this.scene.get('ZoneControls')) this.scene.get('ZoneControls').cleanUp();
        this.scene.remove();
    }
}

module.exports = Zones;
