/*
 * Copyright 2015 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 Link Module.
 Functions for highlighting/selecting links
 */

(function () {
    'use strict';

    // injected refs
    var $log, fs, sus, ts;

    var api,
        td3,
        network,
        enhancedLink = null;    // the link which the mouse is hovering over

    // SVG elements;
    var svg, mouseG;


    // ======== ALGORITHM TO FIND LINK CLOSEST TO MOUSE ========

    function setupMouse(forceG, zoomer) {
        $log.debug('set up mouse handlers for mouse move');
        mouseG = forceG.append('g').attr('id', 'topo-mouse');
        //mouseG.append('circle')
        //    .attr({
        //        r: 5,
        //        opacity: 0
        //    })
        //    .style('fill', 'red');

        svg.on('mouseenter', function () {
            //$log.log('M--ENTER');
            //mouseG.selectAll('circle').attr('opacity', 1);
        })
            .on('mouseleave', function () {
                //$log.log('M--LEAVE');
                //mouseG.selectAll('circle').attr('opacity', 0);
            })
            .on('mousemove', function () {
                var m = d3.mouse(this),
                    sc = zoomer.scale(),
                    tr = zoomer.translate(),
                    mx = (m[0] - tr[0]) / sc,
                    my = (m[1] - tr[1]) / sc;

                //$log.log('M--MOVE', m);

                //mouseG.selectAll('circle')
                //    .attr({
                //        cx: mx,
                //        cy: my
                //    });
                updatePerps({x: mx, y: my}, zoomer);
            });
    }

    function updatePerps(mouse, zoomer) {
        var proximity = 30 / zoomer.scale(),
            perpData, perps, nearest, minDist;

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

        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 mdist(p, m) {
            return Math.sqrt(sq(p.x - m.x) + sq(p.y - m.y));
        }

        function lineSeg(d) {
            return {
                x1: d.source.x,
                y1: d.source.y,
                x2: d.target.x,
                y2: d.target.y
            };
        }

        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;
        }

        if (network.links.length) {
            perpData = [];
            nearest = null;
            minDist = proximity * 2;

            network.links.forEach(function (d) {
                if (!api.showHosts() && d.type() === 'hostLink') {
                    return; // skip hidden host links
                }

                var line = lineSeg(d),
                    point = pdrop(line, mouse),
                    hit = lineHit(line, point, mouse),
                    dist;

                if (hit) {
                    dist = mdist(point, mouse);
                    if (dist < minDist) {
                        minDist = dist;
                        nearest = d;
                    }
                    /*
                     perpData.push({
                     key: d.key,
                     x1: mouse.x,
                     y1: mouse.y,
                     x2: point.x,
                     y2: point.y
                     });
                     */
                }
            });

            /*
             perps = mouseG.selectAll('line')
             .data(perpData, function (d) { return d.key; })
             .attr({
             x1: function (d) { return d.x1; },
             y1: function (d) { return d.y1; },
             x2: function (d) { return d.x2; },
             y2: function (d) { return d.y2; }
             });

             perps.enter().append('line')
             .attr({
             x1: function (d) { return d.x1; },
             y1: function (d) { return d.y1; },
             x2: function (d) { return d.x2; },
             y2: function (d) { return d.y2; }
             })
             .style('stroke-width', 2)
             .style('stroke', 'limegreen');

             perps.exit().remove();
             */

            enhanceNearestLink(nearest);
        }
    }


    function enhanceNearestLink(ldata) {
        // if the new link is same as old link, do nothing
        if (enhancedLink && ldata && enhancedLink.key === ldata.key) return;

        // first, unenhance the currently enhanced link
        if (enhancedLink) {
            unenhance(enhancedLink);
        }
        enhancedLink = ldata;
        if (enhancedLink) {
            enhance(enhancedLink);
        }
    }

    function unenhance(d) {
        d.el.classed('enhanced', false);
        api.portLabelG().selectAll('.portLabel').remove();
    }

    function enhance(d) {
        d.el.classed('enhanced', true);
        $log.debug('[' + (d.srcPort || 'H') + '] ---> [' + d.tgtPort + ']', d.key);

        // Define port label data objects.
        // NOTE: src port is absent in the case of host-links.

        var data = [{
            id: 'topo-port-tgt',
            num: d.tgtPort,
            baseX: d.target.x,
            baseY: d.target.y
        }];

        if (d.srcPort) {
            data.push({
                id: 'topo-port-src',
                num: d.srcPort,
                baseX: d.source.x,
                baseY: d.source.y
            });
        }

        td3.applyPortLabels(data, api.portLabelG());
    }


    // ==========================
    // Module definition

    angular.module('ovTopo')
        .factory('TopoLinkService',
        ['$log', 'FnService', 'SvgUtilService', 'ThemeService',

            function (_$log_, _fs_, _sus_, _ts_) {
                $log = _$log_;
                fs = _fs_;
                sus = _sus_;
                ts = _ts_;

                function initLink(_api_, _td3_) {
                    api = _api_;
                    td3 = _td3_;
                    svg = api.svg;
                    network = api.network;
                    setupMouse(api.forceG, api.zoomer);
                }

                function destroyLink() {
                    svg.on('mouseenter', null)
                        .on('mouseleave', null)
                        .on('mousemove', null);
                }

                return {
                    initLink: initLink,
                    destroyLink: destroyLink
                };
            }]);
}());
