'use strict'

const Button = require('./button');
const isTouchDevice = 'd' in document.documentElement;

module.exports = (scope, inst, options) => {

    const network = inst.network;

    if (isTouchDevice) {
        // Highlight traceback on click
        network.on('click', traceBack);
    } else {
        // Highlight traceback on hover
        network.on('hoverNode', function(params) {
            traceBack(params.node);
        });
        // un-traceback on un-hover
        network.on('blurNode', resetTrace);
    }

    let threshold = 200;
    let eventTime = 0;

    // Click > Expand/Collaps sub tree
    network.on('click', event => {
        let t = new Date();
        setTimeout(() => {
            if (t - eventTime > threshold) {
                expandCollapse(scope, inst, event);
            }
        }, threshold);
    });

    // Click & Hold > show context menu
    network.on('hold', event => {
        eventTime = new Date();
        contextMenu(scope, inst, event);
    });

    // 2x Click > show detail form
    network.on('doubleClick', event => {
        eventTime = new Date();
        detailView(scope, inst, event);
    });

    // Render context menus
    inst.contextMenus = {};
    let canvas = network.canvas.frame.canvas;

    /* TODO context menu needs refactoring */

    // draw buttons
    network.on('afterDrawing', (ctx) => {

        let nodeIds = Object.keys(inst.contextMenus);

        nodeIds.forEach(nodeId => {
            let node = inst.nodes.get(nodeId);
            if (!node || !inst.types[node.type]) {
                return;
            }

            let actions = inst.types[node.type].actions;

            if (!actions || !Object.keys(actions).length) {
                return;
            }

            // compute the button positions
            let menuY = network.getBoundingBox([nodeId]).bottom + 10;
            let menuX = inst.network.getPositions([nodeId])[nodeId].x;

            // create the necessary buttons and place them
            let buttonsWidth = 0;
            let buttons = [];
            Object.keys(actions).forEach(actionName => {
                let action = actions[actionName];
                let button = new Button(ctx, action.label, {
                    color: action.color,
                    fontColor: action.fontColor,
                    hoverColor: action.hoverColor
                });

                // append graph info to the button
                button.node = nodeId;
                button.event = actionName;

                buttonsWidth += buttonsWidth === 0 ? button.width : button.width + 10;
                buttons.push(button);
            });

            // start placing the buttons
            let currentX = menuX - buttonsWidth / 2;
            buttons.forEach(button => {
                button.draw(currentX, menuY);
                currentX += button.width + 10;
            });

            inst.contextMenus[nodeId] = buttons;
        });

        ctx.save();
    });

    // listen for events on context menus
    canvas.addEventListener('mousemove', event => {
        let mouse = network.DOMtoCanvas({x: event.clientX, y: event.clientY});

        Object.keys(inst.contextMenus).forEach(nodeId => {
            let buttons = inst.contextMenus[nodeId];
            buttons.forEach(button => {
                if (mouse.x >= button.x && mouse.x <= button.x + button.width && mouse.y >= button.y && mouse.y <= button.y + button.height) {
                    button.mouseOver();
                } else {
                    button.mouseAway();
                }
            });
        });
    }, false);

    // listen for click event on contex buttons
    canvas.addEventListener('mouseup', event => {
        let mouse = network.DOMtoCanvas({x: event.clientX, y: event.clientY});

        Object.keys(inst.contextMenus).forEach(nodeId => {
            let buttons = inst.contextMenus[nodeId];
            buttons.forEach(button => {
                if (mouse.x >= button.x && mouse.x <= button.x + button.width && mouse.y >= button.y && mouse.y <= button.y + button.height) {
                    button.mouseUp();
                }
            });
        });
    }, false);

    // listen for click event on contex buttons
    canvas.addEventListener('mousedown', event => {
        let mouse = network.DOMtoCanvas({x: event.clientX, y: event.clientY});

        Object.keys(inst.contextMenus).forEach(nodeId => {
            let buttons = inst.contextMenus[nodeId];
            buttons.forEach(button => {
                if (mouse.x >= button.x && mouse.x <= button.x + button.width && mouse.y >= button.y && mouse.y <= button.y + button.height) {
                    button.mouseDown();
                    scope.flow(inst._name + '/' + button.event).write({node: button.node});
                }
            });
        });
    }, false);
};

function expandCollapse (scope, inst, event) {

    const node = event.nodes.length ? inst.nodes.get(event.nodes[0]) : null;

    if (!node) {
        return;
    }

    switch (node.state) {
        case 'expand':
            node.state = 'collapse';
            break;
        case 'loading':
            return;
        default:
            node.state = 'expand';
    }

    // update position before updating the graph
    if (node.id) {
        let pos = inst.network.getPositions(node.id)[node.id];
        node.x = pos.x;
        node.y = pos.y;
    }

    inst.nodes.update(node);

    scope.flow(inst._name + '/' + node.state).write({node: node});
}

function contextMenu (scope, inst, event) {

    const node = event.nodes.length ? inst.nodes.get(event.nodes[0]) : null;

    if (!node || !inst.types[node.type]) {
        return;
    }

    // do not add menu if no actions defined
    let actions = inst.types[node.type].actions;
    if (!actions || !Object.keys(actions).length) {
        return;
    }

    if (!inst.contextMenus[node.id]) {
        inst.contextMenus[node.id] = {};
    } else {
        delete inst.contextMenus[node.id];
    }
}

function detailView () {console.log('Detail view:', arguments)}
function traceBack () {

    //console.log('Trace back:', arguments);

    // TODO touch traceback
    /*if (params.nodes.length) { //Was the click on a node?
        //The node clicked
        var page = params.nodes[0];
        //Highlight in blue all nodes tracing back to central node
        traceBack(page);
    } else {
        resetProperties();
    }*/

    /*if (node != selectedNode) {
        selectedNode = node;
        resetProperties();
        tracenodes = getTraceBackNodes(node);
        traceedges = getTraceBackEdges(tracenodes);
        //Color nodes yellow
        var modnodes = tracenodes.map(function(i){return nodes.get(i);});
        colorNodes(modnodes, 1);
        //Widen edges
        var modedges = traceedges.map(function(i){
            var e=edges.get(i);
            e.color={inherit:"to"};
                return e;
        });
        edgesWidth(modedges, 5);
    }*/
}

function resetTrace () {

    //console.log('Reset trace:', arguments);

    /*if (!isReset) {
        selectedNode = null;
        //Reset node color
        var modnodes = tracenodes.map(function(i){return nodes.get(i);});
        colorNodes(modnodes, 0);
        //Reset edge width and color
        var modedges = traceedges.map(function(i){
            var e=edges.get(i);
            e.color=getEdgeColor(nodes.get(e.to).level);
            return e;
        });
        edgesWidth(modedges, 1);
        tracenodes = [];
        traceedges = [];
    }*/
}

@@ -33,17 +33,17 @@
 uire('./
-b
+B
 utton');

fix "Button" module require