import * as _ from 'lodash';
import {Observable, BehaviorSubject, Subscription} from 'rxjs';
import {
  IXosServiceGraph, IXosServiceInstanceGraphData, IXosServiceGraphNode
} from '../interfaces';
import {IXosDebouncer} from '../../core/services/helpers/debounce.helper';
import {IXosModelStoreService} from '../../datasources/stores/model.store';
import {IXosServiceGraphStore} from './service-graph.store';

export interface IXosServiceInstanceGraphStore {
  get(): Observable<IXosServiceGraph>;
}

export class XosServiceInstanceGraphStore implements IXosServiceInstanceGraphStore {
  static $inject = [
    '$log',
    'XosServiceGraphStore',
    'XosModelStore',
    'XosDebouncer'
  ];

  private CoarseGraphSubscription: Subscription;
  private ServiceInstanceSubscription: Subscription;
  private ServiceInstanceLinkSubscription: Subscription;
  private NetworkSubscription: Subscription;

  // debounced functions
  private handleData;


  // FIXME this is declared also in ServiceGraphStore
  private emptyGraph: IXosServiceGraph = {
    nodes: [],
    links: []
  };

  // graph data store
  private graphData: BehaviorSubject<IXosServiceInstanceGraphData> = new BehaviorSubject({
    serviceGraph: this.emptyGraph,
    serviceInstances: [],
    serviceInstanceLinks: [],
    networks: []
  });

  private d3ServiceInstanceGraph = new BehaviorSubject(this.emptyGraph);

  private serviceGraph: IXosServiceGraph = this.emptyGraph;
  private serviceInstances: any[] = [];
  private serviceInstanceLinks: any[] = [];
  private networks: any[] = [];

  constructor (
    private $log: ng.ILogService,
    private XosServiceGraphStore: IXosServiceGraphStore,
    private XosModelStore: IXosModelStoreService,
    private XosDebouncer: IXosDebouncer
  ) {
    this.$log.info(`[XosServiceInstanceGraphStore] Setup`);

    // we want to have a quiet period of 500ms from the last event before doing anything
    this.handleData = this.XosDebouncer.debounce(this._handleData, 500, this, false);

    this.CoarseGraphSubscription = this.XosServiceGraphStore.getCoarse()
      .subscribe(
        (graph: IXosServiceGraph) => {
          this.combineData(graph, 'serviceGraph');
        }
      );

    this.ServiceInstanceSubscription = this.XosModelStore.query('ServiceInstance', '/core/serviceinstances')
      .subscribe(
        (res) => {
          this.combineData(res, 'serviceInstance');
        },
        (err) => {
          this.$log.error(`[XosServiceInstanceGraphStore] Service Observable: `, err);
        }
      );

    this.ServiceInstanceLinkSubscription = this.XosModelStore.query('ServiceInstanceLink', '/core/serviceinstancelinks')
      .subscribe(
        (res) => {
          this.combineData(res, 'serviceInstanceLink');
        },
        (err) => {
          this.$log.error(`[XosServiceInstanceGraphStore] Service Observable: `, err);
        }
      );

    this.NetworkSubscription = this.XosModelStore.query('Network', '/core/networks')
      .subscribe(
        (res) => {
          this.combineData(res, 'networks');
        },
        (err) => {
          this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
        }
      );

    // observe graphData and build ServiceInstance graph
    this.graphData
      .subscribe(
        (res: IXosServiceInstanceGraphData) => {
          this.$log.debug(`[XosServiceInstanceGraphStore] New graph data received`, res);

          this.graphDataToD3(res);
        },
        (err) => {
          this.$log.error(`[XosServiceInstanceGraphStore] graphData Observable: `, err);
        }
      );
  }

  public get(): Observable<IXosServiceGraph> {
    return this.d3ServiceInstanceGraph;
  }

  // called by all the observables, combine the data in a globla graph observable
  private combineData(data: any, type: 'serviceGraph' | 'serviceInstance' | 'serviceInstanceLink' | 'serviceInterface' | 'networks') {
    switch (type) {
      case 'serviceGraph':
        this.serviceGraph = angular.copy(data);
        break;
      case 'serviceInstance':
        this.serviceInstances = data;
        break;
      case 'serviceInstanceLink':
        this.serviceInstanceLinks = data;
        break;
      case 'networks':
        this.networks = data;
        break;
    }
    this.handleData();
  }

  private _handleData() {
    this.graphData.next({
      serviceGraph: this.serviceGraph,
      serviceInstances: this.serviceInstances,
      serviceInstanceLinks: this.serviceInstanceLinks,
      networks: this.networks
    });
  }

  private getNodeType(n: any) {
    return n.class_names.split(',')[0].toLowerCase();
  }

  private getNodeLabel(n: any) {
    if (this.getNodeType(n) === 'serviceinstance') {
      return n.name ? n.name : n.id;
    }
    return n.humanReadableName ? n.humanReadableName : n.name;
  }

  private d3Id(type: string, id: number) {
    return `${type.toLowerCase()}~${id}`;
  }

  private toD3Node(n: any): IXosServiceGraphNode {
    return {
      id: this.d3Id(this.getNodeType(n), n.id),
      label: this.getNodeLabel(n),
      model: n,
      type: this.getNodeType(n)
    };
  }

  private getServiceInstanceIndexById(l: any, nodes: any[], where: 'source' | 'target'): string {
    if (where === 'source') {
      return _.find(nodes, {id: `serviceinstance~${l.provider_service_instance_id}`});
    }
    else {
      if (l.subscriber_service_id) {
        return _.find(nodes, {id: `service~${l.subscriber_service_id}`});
      }
      else if (l.subscriber_network_id) {
        return _.find(nodes, {id: `network~${l.subscriber_network_id}`});
      }
      else if (l.subscriber_service_instance_id) {
        return _.find(nodes, {id: `serviceinstance~${l.subscriber_service_instance_id}`});
      }
    }
  }

  private getOwnerById(id: number, nodes: any[]): any {
    return _.find(nodes, {id: `service~${id}`});
  }

  private graphDataToD3(data: IXosServiceInstanceGraphData) {
    try {
      // get all the nodes
      let nodes = _.chain(data.serviceGraph.nodes)
        .map(n => {
          // HACK we are receiving node as d3 models
          return n.model;
        })
        .map(n => {
          return this.toD3Node(n);
        })
        .value();

      data.serviceInstances = _.chain(data.serviceInstances)
        .map(n => {
          return this.toD3Node(n);
        })
        .value();
      nodes = nodes.concat(data.serviceInstances);

      data.networks = _.chain(data.networks)
        .filter(n => {
          const subscriber = _.findIndex(data.serviceInstanceLinks, {subscriber_network_id: n.id});
          return subscriber > -1;
        })
        .map(n => {
          return this.toD3Node(n);
        })
        .value();
      nodes = nodes.concat(data.networks);

      let links = data.serviceGraph.links;

      // create the links starting from the coarse ones
      links = _.reduce(data.serviceInstanceLinks, (links, l) => {
        let link =  {
          id: `service_instance_link~${l.id}`,
          source: this.getServiceInstanceIndexById(l, nodes, 'source'),
          target: this.getServiceInstanceIndexById(l, nodes, 'target'),
          model: l,
          d3Class: 'service-instance'
        };
        links.push(link);
        return links;
      }, data.serviceGraph.links);

      const linksToService = _.reduce(data.serviceInstances, (links, n) => {
        if (angular.isDefined(n.model.owner_id)) {
          let link =  {
            id: `owner~${n.id}`,
            source: n,
            target: this.getOwnerById(n.model.owner_id, nodes),
            model: n,
            d3Class: 'owner'
          };
          links.push(link);
        }
        return links;
      }, []);

      links = links.concat(linksToService);

      let graph: IXosServiceGraph = {
        nodes,
        links
      };

      this.d3ServiceInstanceGraph.next(graph);
    } catch (e) {
      this.d3ServiceInstanceGraph.error(e);
    }
  }
}
