'use strict';

angular.module('xos.mcordTopology', [
  'ngResource',
  'ngCookies',
  'ngLodash',
  'ui.router',
  'xos.helpers'
])
.config(($stateProvider) => {
  $stateProvider
  .state('topology', {
    url: '/',
    template: '<m-cord-topology></m-cord-topology>'
  });
})
.config(function($httpProvider){
  $httpProvider.interceptors.push('NoHyperlinks');
})
.directive('mCordTopology', function(){
  return {
    restrict: 'E',
    scope: {},
    bindToController: true,
    controllerAs: 'vm',
    template: '',
    controller: function($element, $interval, XosApi, lodash, TopologyElements, NodeDrawer){

      const el = $element[0];

      let nodes = [];
      let links = [];

      const filterBBU = (instances) => {
        return lodash.filter(instances, i => i.name.indexOf('BBU') >= 0);
      };

      const filterOthers = (instances) => {
        return lodash.filter(instances, i => {
          return (i.name.indexOf('MME') >= 0)
          || (i.name.indexOf('SGW') >= 0)
          || (i.name.indexOf('PGW') >= 0)
        });
      };

      // retrieving instances list
      const getData = () => {

        nodes = TopologyElements.nodes;
        links = TopologyElements.links;
        console.log('-----------------------------');
        console.log(`Fabric Links: ${links.length}`);

        XosApi.Instance_List_GET()
        .then((instances) => {
          addBbuNodes(filterBBU(instances));
          addOtherNodes(filterOthers(instances));

          draw(svg, nodes, links);
        })
        .catch((e) => {
          throw new Error(e);
        });
      };

      const force = d3.layout.force();

      // create svg elements
      const svg = d3.select(el)
        .append('svg')
        .style('width', `${el.clientWidth}px`)
        .style('height', `${el.clientHeight}px`);


      let hStep = el.clientWidth / 3;
      let vStep = el.clientHeight / 5;

      // replace human readable ids with d3 ids
      const buildLinks = (links, nodes) => {
        console.log(`links: ${links.length}`);
        return links.map((l, i) => {
          let source = lodash.findIndex(nodes, {id: l.source});
          let target = lodash.findIndex(nodes, {id: l.target});
          return {
            source: source,
            target: target,
            value: 1,
            id: `link-${i++}`
          };

        });
      };

      // find fabric nodes and center horizontally
      const positionFabricNodes = (nodes) => {
        return lodash.map(nodes, n => {
          if(n.type !== 'fabric'){
            return n;
          }

          n.x = n.x * hStep;
          n.y = n.y * vStep;

          return n;
        });
      };

      const addBbuNodes = (instances) => {

        // calculate bbu hStep
        let bbuHStep = ((el.clientWidth / 2) / (instances.length + 1));

        // create nodes
        let bbuNodes = instances.map((n, i) => {
          return {
            type: 'bbu',
            name: n.name,
            id: `bbu-${n.id}`,
            fixed: true,
            y: vStep * 3,
            x: bbuHStep * (i + 1)
          };
        });

        // create links
        let bbuLinks = bbuNodes.map(n => {
          return {
            source: n.id,
            target: 'fabric2'
          };
        });

        // fake RRU nodes and links
        instances.forEach((n, i) => {
          bbuNodes.push({
            type: 'rru',
            name: 'rru',
            id: `rru-${n.id}`,
            fixed: true,
            y: vStep * 4,
            x: bbuHStep * (i + 1)
          });

          bbuLinks.push({
            source: `rru-${n.id}`,
            target: `bbu-${n.id}`
          });
        })

        nodes = nodes.concat(bbuNodes);

        console.log(`bbuLinks: ${bbuLinks.length}`);

        links = links.concat(bbuLinks);
      };

      // add MME, PGW, SGW nodes
      const addOtherNodes = (instances) => {
        let hStep = ((el.clientWidth / 2) / (instances.length + 1));

        // create nodes
        let otherNodes = instances.map((n, i) => {
          return {
            type: n.name.substring(0, 3),
            name: n.name,
            id: `${n.name.substring(0, 3)}-${n.id}`,
            fixed: true,
            y: vStep * 3,
            x: (el.clientWidth / 2) + (hStep * (i + 1))
          };
        });

        // create links
        let otherLinks = otherNodes.map(n => {
          return {
            source: n.id,
            target: 'fabric4'
          };
        });

        console.log(`otherLinks: ${otherLinks.length}`);

        nodes = nodes.concat(otherNodes);
        links = links.concat(otherLinks);
      }

      // NOTE links get duplicated
      const draw = (svg, nodes, links) => {

        links = buildLinks(links, nodes);

        nodes = positionFabricNodes(nodes);

        // start force layout
        force
          .nodes(nodes)
          .links(links)
          .size([el.clientWidth, el.clientHeight])
          .charge(-20)
          .chargeDistance(200)
          .linkDistance(80)
          .linkStrength(0.1)
          .start();

        // draw links
        var link = svg.selectAll('.link')
          .data(links, d => d.id);
        
        link.enter().append('line')
          .attr({
            class: 'link',
            id: d => d.id,
            opacity: 0
          })
          .transition()
          .duration(1000)
          // .delay((d, i) => 50 * i)
          .attr({
            opacity: 1
          });

        link.exit()
        .remove();

        //draw nodes
        var node = svg.selectAll('.node')
          .data(nodes, d => {
            return d.id
          });
        
        // append a group for any new node
        var enter = node.enter()
          .append('g', d => d.interfaceCfgIdentifier)
          .attr({
            class: d => `${d.type} node`,
            transform: d => `translate(${d.x}, ${d.y})`
          });

        // draw nodes
        NodeDrawer.drawBbus(enter.filter('.bbu'))
        NodeDrawer.drawRrus(enter.filter('.rru'))
        NodeDrawer.drawFabric(enter.filter('.fabric'))
        NodeDrawer.drawOthers(enter.filter(d => {
          return (
            d.type  === 'MME' ||
            d.type === 'SGW' ||
            d.type === 'PGW'
          )
        }));

        // remove nodes
        var exit = node.exit();

        NodeDrawer.removeElements(exit);

        force.on('tick', function() {
          link
            .attr('x1', d => d.source.x )
            .attr('y1', d => d.source.y )
            .attr('x2', d => d.target.x )
            .attr('y2', d => d.target.y );

          node.attr('transform', (d) => `translate(${d.x},${d.y})`);
        });
      };
      
      $interval(() => {
        getData();
      }, 5000);
      getData();

      
    }
  };
});