import './coarse.component.scss';
import * as d3 from 'd3';
import * as $ from 'jquery';
import * as _ from 'lodash';
import {IXosServiceGraphStore} from '../../services/service-graph.store';
import {IXosServiceGraph, IXosServiceGraphNode, IXosServiceGraphLink} from '../../interfaces';
import {XosServiceGraphConfig as config} from '../../graph.config';
import {IXosDebouncer} from '../../../core/services/helpers/debounce.helper';
import {Subscription} from 'rxjs';
import {IXosGraphHelpers} from '../../services/d3-helpers/graph.helpers';
import {IXosServiceGraphReducer, IXosServiceGraphExtender} from '../../services/graph.extender';

class XosCoarseTenancyGraphCtrl {

  static $inject = [
    '$log',
    'XosServiceGraphStore',
    'XosDebouncer',
    'XosGraphHelpers',
    'XosServiceGraphExtender'
  ];

  public graph: IXosServiceGraph;

  private CoarseGraphSubscription: Subscription;
  private svg;
  private forceLayout;
  private linkGroup;
  private nodeGroup;
  private textSize = 20;
  private textOffset = this.textSize / 4;

  // debounced functions
  private renderGraph;

  constructor (
    private $log: ng.ILogService,
    private XosServiceGraphStore: IXosServiceGraphStore,
    private XosDebouncer: IXosDebouncer,
    private XosGraphHelpers: IXosGraphHelpers,
    private XosServiceGraphExtender: IXosServiceGraphExtender
  ) {

  }

  $onInit() {
    this.renderGraph = this.XosDebouncer.debounce(this._renderGraph, 500, this);

    this.CoarseGraphSubscription = this.XosServiceGraphStore.getCoarse()
      .subscribe(
        (graph: IXosServiceGraph) => {
          this.$log.debug(`[XosCoarseTenancyGraph] Coarse Event and render`, graph);

          // id there are no data, do nothing
          if (graph.nodes.length === 0) {
            return;
          }
          this.graph = graph;

          _.forEach(this.XosServiceGraphExtender.getCoarse(), (r: IXosServiceGraphReducer) => {
            graph = r.reducer(graph);
          });
          this.renderGraph();
        },
        err => {
          this.$log.error(`[XosCoarseTenancyGraph] Coarse Event error`, err);
        });

    this.handleSvg();
    this.setupForceLayout();

    $(window).on('resize', () => {
      this.setupForceLayout();
      this.renderGraph();
    });
  }

  $onDestroy() {
    this.CoarseGraphSubscription.unsubscribe();
  }

  private _renderGraph() {
    if (!angular.isDefined(this.graph) || !angular.isDefined(this.graph.nodes) || !angular.isDefined(this.graph.links)) {
      return;
    }
    this.addNodeLinksToForceLayout(this.graph);
    this.renderNodes(this.graph.nodes);
    this.renderLinks(this.graph.links);
  }

  private getSvgDimensions(): {width: number, height: number} {
    return {
      width: $('xos-coarse-tenancy-graph svg').width() || 0,
      height: $('xos-coarse-tenancy-graph svg').height() || 0
    };
  }

  private handleSvg() {
    this.svg = d3.select('svg');

    this.svg.append('svg:defs')
      .selectAll('marker')
      .data(config.markers)
      .enter()
      .append('svg:marker')
      .attr('id', d => d.id)
      .attr('viewBox', d => d.viewBox)
      .attr('refX', d => d.refX)
      .attr('refY', d => d.refY)
      .attr('markerWidth', d => d.width)
      .attr('markerHeight', d => d.height)
      .attr('orient', 'auto')
      .attr('class', d => `${d.id}-marker`)
      .append('svg:path')
      .attr('d', d => d.path);

    this.linkGroup = this.svg.append('g')
      .attr({
        class: 'link-group'
      });

    this.nodeGroup = this.svg.append('g')
      .attr({
        class: 'node-group'
      });
  }

  private collide(n: any) {
    const svgDim = this.getSvgDimensions();
    const x = Math.max(n.width / 2, Math.min(n.x, svgDim.width - (n.width / 2)));
    const y = Math.max(n.height / 2, Math.min(n.y, svgDim.height - (n.height / 2)));
    return `${x}, ${y}`;
  }

  private setupForceLayout() {

    let svgDim = this.getSvgDimensions();

    const tick = () => {

      this.nodeGroup.selectAll('g.node')
        .attr({
          transform: d => `translate(${this.collide(d)})`
        });

      this.linkGroup.selectAll('line')
        .attr({
          x1: l => l.source.x || 0,
          y1: l => l.source.y || 0,
          x2: l => l.target.x || 0,
          y2: l => l.target.y || 0,
        });
    };

    this.forceLayout = d3.layout.force()
      .size([svgDim.width, svgDim.height])
      .linkDistance(config.force.linkDistance)
      .charge(config.force.charge)
      .gravity(config.force.gravity)
      .on('tick', tick);
  }

  private addNodeLinksToForceLayout(data: IXosServiceGraph) {
    this.forceLayout
      .nodes(data.nodes)
      .links(data.links)
      .start();
  }

  private renderNodes(nodes: IXosServiceGraphNode[]) {
    const self = this;
    const node = this.nodeGroup
      .selectAll('g.node')
      .data(nodes, n => n.id);

    const svgDim = this.getSvgDimensions();
    const entering = node.enter()
      .append('g')
      .attr({
        id: n => n.id,
        class: n => `node ${this.XosGraphHelpers.parseElemClasses(n.d3Class)}`,
        transform: `translate(${svgDim.width / 2}, ${svgDim.height / 2})`
      })
      .call(this.forceLayout.drag)
      .on('mousedown', () => {
        d3.event.stopPropagation();
      })
      .on('mouseup', (d) => {
        d.fixed = true;
      });

    entering.append('rect')
      .attr({
        rx: config.node.radius,
        ry: config.node.radius
      });

    entering.append('text')
      .attr({
        'text-anchor': 'middle',
        'transform': `translate(0,${this.textOffset})`
      })
      .text(n => n.label);
      // .text(n => `${n.id} - ${n.label}`);

    const existing = node.selectAll('rect');

    // resize node > rect as contained text

    existing.each(function(d: any) {
      const textBBox = self.XosGraphHelpers.getSiblingTextBBox(this);
      const rect = d3.select(this);
      rect.attr({
        width: textBBox.width + config.node.padding,
        height: textBBox.height + config.node.padding,
        x: textBBox.x - (config.node.padding / 2),
        y: (textBBox.y + self.textOffset) - (config.node.padding / 2)
      });
      d.width = textBBox.width + config.node.padding;
      d.height = textBBox.height + config.node.padding;
    });

  }

  private renderLinks(links: IXosServiceGraphLink[]) {
    const link = this.linkGroup
      .selectAll('line')
      .data(links, l => l.id);

    const entering = link.enter();

    // TODO read classes from graph links

    entering.append('line')
      .attr({
        id: n => n.id,
        class: l => `link ${this.XosGraphHelpers.parseElemClasses(l.d3Class)}`,
        'marker-start': 'url(#arrow)'
      });
  }
}

export const XosCoarseTenancyGraph: angular.IComponentOptions = {
  template: require('./coarse.component.html'),
  controllerAs: 'vm',
  controller: XosCoarseTenancyGraphCtrl,
};
