/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

(function(falcon) {
  "use strict";

  dust.loadSource(dust.compile($('#lineage-info-tmpl').html(), 'info'));
  var CIRCLE_RADIUS = 12, RANK_SEPARATION = 120, LABEL_WIDTH = 120, LABEL_HEIGHT = 80, LABEL_PADDING = 20;
  var PREFIX = '/api/metadata/lineage';

  var data = {
    queue : {},
    nodes : {},
    edges : {},
    active_node_id : null
  };

  function process_queue(done_cb) {
    var q = data.queue;
    if (q.length == 0) {
      done_cb();
      return;
    }

    function filter_node(n) {
      return n.type === 'process-instance' || n.type === 'feed-instance';
    }

    function is_nonterminal_label(e) {
      return e._label === 'input' || e._label === 'output';
    }

    function visit_neighbor(p) {
      var vid = p.id, depth = p.depth;
      if (depth == 0) {
        process_queue(done_cb);
        return;
      }
      falcon.getJson(PREFIX + '/vertices/' + vid + '/both', function(resp) {
        for (var i = 0; i < resp.results.length; ++i) {
          var n = resp.results[i];
          if (data.nodes[n._id] !== undefined || !filter_node(n)) {
            continue;
          }
          data.nodes[n._id] = n;
          q.push({'id': n._id, 'depth': depth - 1});
        }
      }).fail(falcon.ajaxFailureHandler)
        .always(function() {
          process_queue(done_cb);
        });
    }

    var v = data.queue.pop();
    falcon.getJson(PREFIX + '/vertices/' + v.id + '/bothE', function(resp) {
      var terminal_has_in_edge = false, terminal_has_out_edge = false;
      var node = data.nodes[v.id];
      for (var i = 0; i < resp.results.length; ++i) {
        var e = resp.results[i];
        if (is_nonterminal_label(e)) {
          terminal_has_in_edge = terminal_has_in_edge || e._inV == v.id;
          terminal_has_out_edge = terminal_has_out_edge || e._outV == v.id;
        }
        if (data.edges[e._id] !== undefined) {
          continue;
        }
        data.edges[e._id] = e;
      }
      node.is_terminal = !(terminal_has_in_edge && terminal_has_out_edge);
    }).fail(falcon.ajaxFailureHandler)
      .always(function () {
        visit_neighbor(v);
      });
  }

  function draw_graph() {
    var svg = d3.select('#lineage-graph').html('').append('svg:g');

    var LINE_FUNCTION = d3.svg.line()
      .x(function(d) { return d.x; })
      .y(function(d) { return d.y; })
      .interpolate('basis');

    function draw_node_functor(node_map) {
      function expand_node(d) {
        return function() {
          data.queue.push({'id': d._id, 'depth': 1});
          update_graph();
        };
      }

      function show_info_functor(d) {
        return function() {
          svg.selectAll('.lineage-node').classed('lineage-node-active', false);
          d3.select(this).classed('lineage-node-active', true);
          data.active_node_id = d._id;
          falcon.getJson(PREFIX + '/vertices/properties/' + d._id + '?relationships=true', function(resp) {
            dust.render('info', resp, function(err, out) {
              $('#lineage-info-panel').html(out);
            });
          }).fail(falcon.ajaxFailureHandler);
        };
      }

      return function(id, d) {
        var data = node_map[id];
        var r = svg.append('g')
          .attr('transform', 'translate(' + d.x + ',' + d.y + ')');

        var c = r.append('circle')
          .attr('data-node-id', id)
          .attr('class', 'lineage-node lineage-node-' + data.type)
          .attr('r', CIRCLE_RADIUS)
          .on('click', show_info_functor(data));

        if (!data.is_terminal) {
          c.on('dblclick', expand_node(data));
        } else {
          c.classed('lineage-node-terminal', true);
        }

        var name = node_map[id].name;
        r.append('title').text(name);

        var fo = r.append('foreignObject')
          .attr('transform', 'translate(' + (-LABEL_WIDTH / 2) + ', ' + LABEL_PADDING + ' )')
          .attr('width', LABEL_WIDTH)
          .attr('height', LABEL_HEIGHT);

        fo.append('xhtml:div').text(name)
          .attr('class', 'lineage-node-text');
      };
    }

    function draw_edge(layout) {
      return function(e, u, v, value) {
        var r = svg.append('g').attr('class', 'lineage-link');
        r.append('path')
          .attr('marker-end', 'url(#arrowhead)')
          .attr('d', function() {
            var points = value.points;

            var source = layout.node(u);
            var target = layout.node(v);

            var p = points.length === 0 ? source : points[points.length - 1];

            var r = CIRCLE_RADIUS;
            var sx = p.x, sy = p.y, tx = target.x, ty = target.y;
            var l = Math.sqrt((tx - sx) * (tx - sx) + (ty - sy) * (ty - sy));
            var dx = r / l * (tx - sx), dy = r / l * (ty - sy);

            points.unshift({'x': source.x, 'y': source.y});
            points.push({'x': target.x - dx, 'y': target.y - dy});
            return LINE_FUNCTION(points);
        });
      };
    }

    var node_map = {};
    var g = new dagre.Digraph();
    for (var k in data.nodes) {
      var n = data.nodes[k];
      g.addNode(n._id, { 'width': CIRCLE_RADIUS * 2 + LABEL_WIDTH, 'height': CIRCLE_RADIUS * 2 + LABEL_HEIGHT});
      node_map[n._id] = n;
    }

    for (var k in data.edges) {
      var e = data.edges[k];
      var src = node_map[e._inV], dst = node_map[e._outV];
      if (src !== undefined && dst !== undefined) {
        g.addEdge(null, e._outV, e._inV);
      }
    }

    var layout = dagre.layout().rankSep(RANK_SEPARATION).rankDir('LR').run(g);
    layout.eachEdge(draw_edge(layout));
    layout.eachNode(draw_node_functor(node_map));

    function post_render() {
      svg
        .append('svg:defs')
        .append('svg:marker')
        .attr('id', 'arrowhead')
        .attr('viewBox', '0 0 10 10')
        .attr('refX', 8)
        .attr('refY', 5)
        .attr('markerUnits', 'strokeWidth')
        .attr('markerWidth', 8)
        .attr('markerHeight', 5)
        .attr('orient', 'auto')
        .attr('style', 'fill: #ccc')
        .append('svg:path')
        .attr('d', 'M 0 0 L 10 5 L 0 10 z');
    }

    var bb = layout.graph();
    $('#lineage-graph').attr('width', bb.width);
    $('#lineage-graph').attr('height', bb.height);

    post_render();
  }

  function update_graph() {
    process_queue(function() {
      draw_graph();
      var id = data.active_node_id;
      if (id !== null) {
        d3.select('.node[data-node-id="' + id + '"]').classed('node-active', true);
      }
    });
  }

  falcon.load_lineage_graph = function(entityId, instance_name) {
    var node_name = entityId + '/' + instance_name;
    falcon.getJson(PREFIX + '/vertices?key=name&value=' + node_name, function(resp) {
      var n = resp.results[0];
      data.queue = [{'id': n._id, 'depth': 1}];
      data.nodes = {};
      data.nodes[n._id] = n;
      update_graph();
      $('#lineage-modal').modal('show');
    }).fail(falcon.ajaxFailureHandler);
  };
})(falcon);
