/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 ONOS GUI -- Topology Select Module.
 */

(function () {
    'use strict';

    var t2zs, t2ddp;

    // internal state
    var instance,
        consumeClick,
        zoomer,
        previousNearestLink;    // previous link to mouse position

    function mouseClickHandler() {
        if (d3.event.defaultPrevented) return;

        if (!d3.event.shiftKey) {
            this.clearSelection();
        }

        if (!this.clickConsumed()) {
            if (previousNearestLink) {
                this.selectObject(previousNearestLink, true);
            }
        }
    }

    // Select Links
    function mouseMoveHandler(ev) {
        var mp = getLogicalMousePosition(this),
            link = computeNearestLink(mp);

        if (link) {
            if (previousNearestLink && previousNearestLink !== link) {
                previousNearestLink.unenhance();
            }
            link.enhance();
        } else if (previousNearestLink) {
            previousNearestLink.unenhance();
        }

        previousNearestLink = link;
    }

    function getLogicalMousePosition(container) {
        var m = d3.mouse(container),
            sc = zoomer.scale(),
            tr = zoomer.translate(),
            mx = (m[0] - tr[0]) / sc,
            my = (m[1] - tr[1]) / sc;
        return { x: mx, y: my };
    }

    function sq(x) {
        return x * x;
    }

    function mdist(p, m) {
        return Math.sqrt(sq(p.x - m.x) + sq(p.y - m.y));
    }

    function prox(dist) {
        return dist / zoomer.scale();
    }

    function computeNearestLink(mouse) {
        var proximity = prox(30),
            nearest = null,
            minDist;

        function pdrop(line, mouse) {
            var x1 = line.x1,
                y1 = line.y1,
                x2 = line.x2,
                y2 = line.y2,
                x3 = mouse.x,
                y3 = mouse.y,
                k = ((y2 - y1) * (x3 - x1) - (x2 - x1) * (y3 - y1)) /
                    (sq(y2 - y1) + sq(x2 - x1)),
                x4 = x3 - k * (y2 - y1),
                y4 = y3 + k * (x2 - x1);
            return { x: x4, y: y4 };
        }

        function lineHit(line, p, m) {
            if (p.x < line.x1 && p.x < line.x2) return false;
            if (p.x > line.x1 && p.x > line.x2) return false;
            if (p.y < line.y1 && p.y < line.y2) return false;
            if (p.y > line.y1 && p.y > line.y2) return false;
            // line intersects, but are we close enough?
            return mdist(p, m) <= proximity;
        }

        var links = [];

        if (instance.region.model.get('links')) {
            links = instance.region.regionLinks();
        }

        if (links.length) {
            minDist = proximity * 2;

            links.forEach(function (d) {
                var line = d.get('position'),
                    point,
                    hit,
                    dist;

                // TODO: Reinstate when showHost() is implemented
                // if (!api.showHosts() && d.type() === 'hostLink') {
                //     return; // skip hidden host links
                // }

                if (line) {
                    point = pdrop(line, mouse);
                    hit = lineHit(line, point, mouse);
                    if (hit) {
                        dist = mdist(point, mouse);
                        if (dist < minDist) {
                            minDist = dist;
                            nearest = d;
                        }
                    }
                }
            });
        }

        return nearest;
    }

    var SelectionService = function () {
        instance = this;
        this.selectedNodes = [];
    };

    SelectionService.prototype = {
        init: function () {
            zoomer = t2zs.getZoomer();

            var svg = d3.select('#topo2');
            svg.on('mousemove', mouseMoveHandler);
            svg.on('click', mouseClickHandler.bind(this));
        },
        updateDetails: function () {

            var nodeCount =  this.selectedNodes.length;

            if (nodeCount === 1) {
                this.selectedNodes[0].showDetails();
            } else if (nodeCount > 1)  {
                t2ddp.showMulti(this.selectedNodes);
            } else {
                t2ddp.hide();
            }
        },
        selectObject: function (node, multiSelectEnabled) {

            var event = d3.event;

            if (multiSelectEnabled && !event.shiftKey || !multiSelectEnabled) {
                this.clearSelection();
            }

            var nodeIndex = _.indexOf(this.selectedNodes, node);

            if (nodeIndex < 0) {
                this.selectedNodes.push(node);
                node.select();
            } else {
                this.removeNode(node, nodeIndex);
            }

            this.updateDetails();
        },
        removeNode: function (node, index) {
            this.selectedNodes.splice(index, 1);
            node.deselect();
        },
        clearSelection: function () {
            _.each(this.selectedNodes, function (node) {
                node.deselect();
            });

            this.selectedNodes = [];
            this.updateDetails();
        },
        clickConsumed: function (x) {
            var cc = consumeClick;
            consumeClick = Boolean(x);
            return cc;
        }
    };

    angular.module('ovTopo2')
    .factory('Topo2SelectService', [
        'Topo2ZoomService', 'Topo2DeviceDetailsPanel',
        function (_t2zs_, _t2ddp_) {
            t2zs = _t2zs_;
            t2ddp = _t2ddp_;
            return instance || new SelectionService();
        }
    ]);

})();
