/*
 * Copyright 2014 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.
 */

/*
 Sample module file to illustrate framework integration.

 @author Simon Hunt
 */

(function (onos) {
    'use strict';

    var pi = Math.PI,
        svg,
        dotG,
        nCircles = 12,
        circleData = [],
        dotId = 0,
        angle = 360 / nCircles,
        baseAngle = -90 - angle,
        groupRadius = 120,
        dotRadius = 24,
        dotMoveMs = 800,
        dotAppearMs = 300,
        dotEase = 'elastic',
        colorScale = d3.scale.linear()
            .domain([-pi/2, 2*pi/4, 3*pi/2])
            .range(['green', 'goldenrod', 'blue']);

    // set the size of the SVG layer to match that of the view
    function sizeSvg(view) {
        svg.attr({
            width: view.width(),
            height: view.height()
        });
    }

    // gets invoked only the first time the view is loaded
    function preload(view, ctx) {
        // prepare our SVG layer...
        svg = view.$div.append('svg');
        sizeSvg(view);
        dotG = svg.append('g').attr('id', 'dots');
    }

    // gets invoked just before our view is loaded
    function reset(view) {
        // clear dot group and reset circle data
        dotG.html('');
        circleData = [];
        // also clear text, if any
        svg.selectAll('text').remove();
    }

    function updateCirclePositions(view, addNew) {
        var w = view.width(),
            h = view.height(),
            ox = w / 2,
            oy = h / 2;

        // reposition existing dots
        circleData.forEach(function (c, i) {
            var inc = addNew ? 1 : 0,
                theta = ((i + inc) * angle + baseAngle) * pi/180,
                dx = Math.cos(theta) * groupRadius,
                dy = Math.sin(theta) * groupRadius,
                x = ox + dx,
                y = oy + dy;
            if (!addNew && i === 0) {
                x = ox;
                y = oy;
            }
            c.cx = x;
            c.cy = y;
            c.rgb = colorScale(theta);
        });

        if (addNew) {
            // introduce a new dot
            circleData.unshift({
                cx: ox,
                cy: oy,
                id: dotId++
            });
        }

        // +1 to account for the circle in the center..
        if (circleData.length > nCircles + 1) {
            circleData.splice(nCircles + 1, 1);
        }
    }

    function doCircles(view) {
        var ox = view.width() / 2,
            oy = view.height() / 2,
            stroke = 'black',
            fill = 'red',
            hoverFill = 'magenta';

        // move existing circles, and add a new one
        updateCirclePositions(view, true);

        var circ = dotG.selectAll('circle')
            .data(circleData, function (d) { return d.id; });

        // operate on existing elements
        circ.on('mouseover', null)
            .on('mouseout', null)
            .on('click', null)
            .transition()
            .duration(dotMoveMs)
            .ease(dotEase)
            .attr({
                cx: function (d) { return d.cx; },
                cy: function (d) { return d.cy; }
            })
            .style({
                cursor: 'default',
                fill: function (d) { return d.rgb; }
            });

        // operate on entering elements
        circ.enter()
            .append('circle')
            .attr({
                cx: function (d) { return d.cx; },
                cy: function (d) { return d.cy; },
                r: 0
            })
            .style({
                fill: fill,
                stroke: stroke,
                'stroke-width': 3.5,
                cursor: 'pointer',
                opacity: 0
            })
            .on('mouseover', function (d) {
                d3.select(this).style('fill', hoverFill);
            })
            .on('mouseout', function (d) {
                d3.select(this).style('fill', fill);
            })
            .on('click', function (d) {
                setTimeout(function() {
                    doCircles(view, true);
                }, 10);
            })
            .transition()
            .delay(dotMoveMs)
            .duration(dotAppearMs)
            .attr('r', dotRadius)
            .style('opacity', 1);

        // operate on exiting elements
        circ.exit()
            .transition()
            .duration(750)
            .style('opacity', 0)
            .attr({
                cx: ox,
                cy: oy,
                r: groupRadius - dotRadius
            })
            .remove();
    }

    function load(view, ctx) {
        var ctxText = ctx ? 'Context is "' + ctx + '"' : '';

        // display our view context
        if (ctxText) {
            svg.append('text')
                .text(ctxText)
                .attr({
                    x: 20,
                    y: '1.5em'
                })
                .style({
                    fill: 'darkgreen',
                    'font-size': '20pt'
                });
        }

        doCircles(view);
    }

    function resize(view, ctx) {
        sizeSvg(view);
        updateCirclePositions(view);

        // move exiting dots into new positions, relative to view size
        var circ = dotG.selectAll('circle')
            .data(circleData, function (d) { return d.id; });
        circ.attr({
                cx: function (d) { return d.cx; },
                cy: function (d) { return d.cy; }
            });
    }

    // == register our view here, with links to lifecycle callbacks

    onos.ui.addView('sample', {
        preload: preload,
        reset: reset,
        load: load,
        resize: resize
    });

}(ONOS));
