(function () {
  'use strict';

  angular.module('xos.serviceTopology')
  .service('Services', function($resource){
    return $resource('/xos/services/:id', {id: '@id'});
  })
  .service('Tenant', function($resource){
    return $resource('/xos/tenants', {id: '@id'}, {
      queryVsgInstances: {
        method: 'GET',
        isArray: true,
        interceptor: {
          response: (res) => {

            // NOTE
            // Note that VCPETenant is now VSGTenant.

            let instances = [];

            angular.forEach(res.data, (tenant) => {
              let info = JSON.parse(tenant.service_specific_attribute);
              if(info && info.instance_id){
                instances.push(info.instance_id);
              }
            });

            return instances;
          }
        }
      },
      getSubscriberTag: {
        method: 'GET',
        isArray: true,
        interceptor: {
          response: (res) => {
            // NOTE we should receive only one vOLT tenant here
            return JSON.parse(res.data[0].service_specific_attribute);
          }
        }
      }
    });
  })
  .service('Ceilometer', function($http, $q, Instances) {

    /**
    * Get stats for a single instance
    */
    this.getInstanceStats = (instanceUuid) => {
      let deferred = $q.defer();

      $http.get('/xoslib/xos-instance-statistics', {params: {'instance-uuid': instanceUuid}})
      .then((res) => {
        deferred.resolve(res.data);
      })
      .catch((e) => {
        deferred.reject(e);
      })

      return deferred.promise;
    };

    /**
    * Collect stats for an array of instances
    */
    this.getInstancesStats = (instances) => {
      let deferred = $q.defer();
      let instancePromises = [];
      let instanceList = [];

      // retrieve instance details
      instances.forEach((instanceId) => {
        instancePromises.push(Instances.get({id: instanceId}).$promise);
      });

      // get all instance data
      $q.all(instancePromises)
      .then((_instanceList) => {
        instanceList = _instanceList;
        let promises = [];
        // foreach instance query stats
        instanceList.forEach((instance) => {
          promises.push(this.getInstanceStats(instance.instance_uuid));
        });
        return $q.all(promises);
      })
      .then(stats => {
        // augment instance with stats information
        instanceList.map((instance, i) => {
          instance.stats = stats[i];
        });
        deferred.resolve(instanceList);
      })
      .catch(deferred.reject);

      return deferred.promise;
    };

    this.getContainerStats = (containerName) => {
      const deferred = $q.defer();

      let res = {};

      $http.get('/xoslib/meterstatistics', {params: {'resource': containerName}})
      .then((containerStats) => {
        res.stats = containerStats.data;
        return $http.get('/xoslib/meterstatistics', {params: {'resource': `${containerName}-eth0`}})
      })
      .then((portStats) => {
        res.port = {
          eth0: portStats.data
        };
        return $http.get('/xoslib/meterstatistics', {params: {'resource': `${containerName}-eth1`}})
      })
      .then((portStats) => {
        res.port.eth1 = portStats.data;
        deferred.resolve(res);
      })
      .catch((e) => {
        deferred.reject(e);
      })

      return deferred.promise;
    }
  })
  .service('Slice', function($resource){
    return $resource('/xos/slices', {id: '@id'});
  })
  .service('Instances', function($resource){
    return $resource('/xos/instances/:id', {id: '@id'});
  })
  .service('Node', function($resource, $q, Instances){
    return $resource('/xos/nodes', {id: '@id'}, {
      queryWithInstances: {
        method: 'GET',
        isArray: true,
        interceptor: {
          response: function(res){

            // TODO update the API to include instances in nodes
            // http://stackoverflow.com/questions/14573102/how-do-i-include-related-model-fields-using-django-rest-framework

            const deferred = $q.defer();

            let requests = [];

            angular.forEach(res.data, (node) => {
              requests.push(Instances.query({node: node.id}).$promise);
            })

            $q.all(requests)
            .then((list) => {
              res.data.map((node, i) => {
                node.instances = list[i];
                return node;
              });
              deferred.resolve(res.data);
            })

            return deferred.promise;
          }
        }
      }
    });
  })
  .service('Subscribers', function($resource, $q, SubscriberDevice){
    return $resource('/xos/subscribers/:id', {id: '@id'}, {
      queryWithDevices: {
        method: 'GET',
        isArray: true,
        interceptor: {
          response: function(res){

            /**
            * For each subscriber retrieve devices and append them
            */

            let deferred = $q.defer();

            let requests = [];

            angular.forEach(res.data, (subscriber) => {
              requests.push(SubscriberDevice.query({id: subscriber.id}).$promise);
            })

            $q.all(requests)
            .then((list) => {

              // adding devices

              res.data.map((subscriber, i) => {
                subscriber.devices = list[i];
                subscriber.type = 'subscriber';

                subscriber.devices.map(d => d.type = 'device')

                return subscriber;
              });

              // faking to have 2 subscriber
              // res.data.push(angular.copy(res.data[0]));

              deferred.resolve(res.data);
            })

            return deferred.promise;
          }
        }
      },
      getWithDevices: {
        method: 'GET',
        isArray: false,
        interceptor: {
          response: (res) => {
            let d = $q.defer();

            SubscriberDevice.query({id: res.data.id}).$promise
            .then(devices => {
              devices.map(d => d.type = 'device');
              res.data.devices = devices;
              res.data.type = 'subscriber';
              d.resolve(res.data);
            })
            .catch(err => {
              d.reject(err);
            });

            return d.promise;
          }
        }
      }
    });
  })
  .service('SubscriberDevice', function($resource){
    return $resource('/xoslib/rs/subscriber/:id/users/', {id: '@id'});
  })
  .service('ServiceRelation', function($q, lodash, Services, Tenant, Slice, Instances){

    // count the mas depth of an object
    const depthOf = (obj) => {
      var depth = 0;
      if (obj.children) {
        obj.children.forEach(function (d) {
          var tmpDepth = depthOf(d);
          if (tmpDepth > depth) {
            depth = tmpDepth
          }
        })
      }
      return 1 + depth
    };

    // find all the relation defined for a given root
    const findLevelRelation = (tenants, rootId) => {
      return lodash.filter(tenants, service => {
        return service.subscriber_service === rootId;
      });
    };

    const findSpecificInformation = (tenants, rootId) => {
      var tenants = lodash.filter(tenants, service => {
        return service.provider_service === rootId && service.subscriber_tenant;
      });

      var info;

      tenants.forEach((tenant) => {
        if(tenant.service_specific_attribute){
          info = JSON.parse(tenant.service_specific_attribute);
        }
      });

      return info;
    };

    // find all the service defined by a given array of relations
    const findLevelServices = (relations, services) => {
      const levelServices = [];
      lodash.forEach(relations, (tenant) => {
        var service = lodash.find(services, {id: tenant.provider_service});
        levelServices.push(service);
      });
      return levelServices;
    };

    const buildLevel = (tenants, services, rootService, rootTenant, parentName = null) => {

      // build an array of unlinked services
      // these are the services that should still placed in the tree
      var unlinkedServices = lodash.difference(services, [rootService]);

      // find all relations relative to this rootElement
      const levelRelation = findLevelRelation(tenants, rootService.id);
      // find all items related to rootElement
      const levelServices = findLevelServices(levelRelation, services);

      // remove this item from the list (performance
      unlinkedServices = lodash.difference(unlinkedServices, levelServices);

      rootService.service_specific_attribute = findSpecificInformation(tenants, rootService.id);

      const tree = {
        name: rootService.humanReadableName,
        parent: parentName,
        type: 'service',
        service: rootService,
        tenant: rootTenant,
        children: []
      };

      lodash.forEach(levelServices, (service) => {
        let tenant = lodash.find(tenants, {subscriber_tenant: rootTenant.id, provider_service: service.id});
        tree.children.push(buildLevel(tenants, unlinkedServices, service, tenant, rootService.humanReadableName));
      });

      // if it is the last element append internet
      if(tree.children.length === 0){
        tree.children.push({
          name: 'Router',
          type: 'router',
          children: []
        });
      }

      return tree;
    };

    const buildSubscriberServiceTree = (services, tenants, subscriber = {id: 1, name: 'fakeSubs'}) => {

      // find the root service
      // it is the one attached to subsriber_root
      // as now we have only one root so this can work
      const rootTenant = lodash.find(tenants, {subscriber_root: subscriber.id});
      const rootService = lodash.find(services, {id: rootTenant.provider_service});

      const serviceTree = buildLevel(tenants, services, rootService, rootTenant);

      return {
        name: subscriber.name,
        parent: null,
        type: 'subscriber',
        children: [serviceTree]
      };

    };

    // applying domain knowledge to build the global service tree
    const buildServiceTree = (services, tenants) => {

      // TODO refactor
      const buildChild = (services, tenants, currentService) => {

        const response = {
          type: 'service',
          name: currentService.humanReadableName,
          service: currentService
        };

        let tenant = lodash.find(tenants, {subscriber_service: currentService.id});
        if(tenant){
          let next = lodash.find(services, {id: tenant.provider_service});
          response.children = [buildChild(services, tenants, next)];
        }
        else {
          response.children = [
            {
              name: 'Router',
              type: 'router',
              children: []
            }
          ]
        }
        delete currentService.id; // conflict with d3
        return response;
      }
      let baseService = lodash.find(services, {id: 3});

      const baseData = {
        name: 'Subscriber',
        type: 'subscriber',
        parent: null,
        children: [buildChild(services, tenants, baseService)]
      };
      return baseData;
    };

    const getBySubscriber = (subscriber) => {
      var deferred = $q.defer();
      var services, tenants;
      Services.query().$promise
      .then((res) => {
        services = res;
        return Tenant.query().$promise;
      })
      .then((res) => {
        tenants = res;
        deferred.resolve(buildSubscriberServiceTree(services, tenants, subscriber));
      })
      .catch((e) => {
        throw new Error(e);
      });

      return deferred.promise;
    };

    const get = () => {
      var deferred = $q.defer();
      var services, tenants;
      Services.query().$promise
      .then((res) => {
        services = res;
        return Tenant.query({kind: 'coarse'}).$promise;
      })
      .then((res) => {
        tenants = res;
        deferred.resolve(buildServiceTree(services, tenants));
      })
      .catch((e) => {
        throw new Error(e);
      });

      return deferred.promise;
    }

    // export APIs
    return {
      get: get,
      buildServiceTree: buildServiceTree,
      getBySubscriber: getBySubscriber,
      buildLevel: buildLevel,
      buildSubscriberServiceTree: buildSubscriberServiceTree,
      findLevelRelation: findLevelRelation,
      findLevelServices: findLevelServices,
      depthOf: depthOf,
      findSpecificInformation: findSpecificInformation
    }
  });

}());