
/*
 * Copyright 2017-present Open Networking Foundation

 * Licensed 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.
 */

import * as _ from 'lodash';
import * as angular from 'angular';
import 'angular-mocks';
import {IXosGraphStore, XosGraphStore} from './graph.store';
import {Subject} from 'rxjs/Subject';
import {Graph} from 'graphlib';
import {XosDebouncer} from '../../core/services/helpers/debounce.helper';
import {IWSEvent} from '../../datasources/websocket/global';

interface ITestXosGraphStore extends IXosGraphStore {

  // state
  serviceGraph: Graph;

  // private methods
  getNodeId: any;
  getModelType: any;
  addNode: any;
  addEdge: any;
  nodesFromGraph: any;

  // observables
  ServiceInstanceSubscription: any;
  ServiceInstanceLinkSubscription: any;
}

let service: ITestXosGraphStore;

let scope: ng.IRootScopeService;

const services = [
  {
    id: 1,
    class_names: 'Service,XOSBase',
    name: 'Service 1'
  },
  {
    id: 2,
    class_names: 'Service,XOSBase',
    name: 'Service 2'
  }
];

const servicedependencies = [
  {
    id: 1,
    class_names: 'ServiceDependency,XOSBase',
    provider_service_id: 2,
    subscriber_service_id: 1
  }
];

const serviceInstances = [
  {
    id: 1,
    class_names: 'ServiceInstance,XOSBase',
    name: 'ServiceInstance 1',
    owner_id: 1
  },
  {
    id: 2,
    class_names: 'ServiceInstance,XOSBase',
    name: 'ServiceInstance 2',
    owner_id: 2
  }
];

const serviceInstanceLinks = [
  {
    id: 1,
    class_names: 'ServiceInstanceLink,XOSBase',
    provider_service_instance_id: 1,
    subscriber_service_instance_id: 2,
  }
];

const subject_services = new Subject();
const subject_servicedependency = new Subject();
const subject_serviceinstances = new Subject();
const subject_serviceinstancelinks = new Subject();
const subject_websocket = new Subject();

let MockModelStore = {
  query: jasmine.createSpy('XosModelStore.query')
    .and.callFake((model) => {
      if (model === 'Service') {
        return subject_services.asObservable();
      }
      else if (model === 'ServiceDependency') {
        return subject_servicedependency.asObservable();
      }
      else if (model === 'ServiceInstance') {
        return subject_serviceinstances.asObservable();
      }
      else if (model === 'ServiceInstanceLink') {
        return subject_serviceinstancelinks.asObservable();
      }
    })
};

let MockWebSocket = {
  list: jasmine.createSpy('WebSocket.list')
    .and.returnValue(subject_websocket)
};


describe('The XosGraphStore service', () => {

  beforeEach(() => {
    angular.module('XosGraphStore', [])
      .service('XosGraphStore', XosGraphStore)
      .value('XosModelStore', MockModelStore)
      .value('WebSocket', MockWebSocket)
      .service('XosDebouncer', XosDebouncer);

    angular.mock.module('XosGraphStore');
  });

  beforeEach(angular.mock.inject((XosGraphStore: ITestXosGraphStore,
                                  $rootScope: ng.IRootScopeService,
                                  _$q_: ng.IQService) => {

    service = XosGraphStore;
    scope = $rootScope;

  }));

  describe('when started', () => {

    let subscription;

    it('should load services and service-dependency and add nodes to the graph', (done) => {
      let event = 0;
      subscription = service.get().subscribe(
        (graph: Graph) => {
          if (event === 1) {
            expect(graph.nodes().length).toBe(services.length);
            expect(graph.nodes()).toEqual(['service~1', 'service~2']);
            expect(graph.edges().length).toBe(servicedependencies.length);
            expect(graph.edges()).toEqual([{v: 'service~1', w: 'service~2'}]);
            done();
          }
          else {
            event = event + 1;
          }
        }
      );
      subject_services.next(services);
      subject_servicedependency.next(servicedependencies);
      scope.$apply();
    });

    afterEach(() => {
      subscription.unsubscribe();
    });
  });

  describe('when an observed model is removed', () => {

    let subscription;

    beforeEach(() => {
      subject_services.next([]);
      subject_servicedependency.next([]);
      subject_services.next(services);
      subject_servicedependency.next(servicedependencies);
      service.addServiceInstances();
      subject_serviceinstances.next([serviceInstances[0]]);
    });

    it('should be removed from the graph', (done) => {
      let event = 0;
      subscription = service.get().subscribe(
        (graph: Graph) => {
          if (event === 1) {
            expect(graph.nodes().length).toBe(0);
            expect(graph.nodes()).toEqual([]);
            expect(graph.edges().length).toBe(0);
            expect(graph.edges()).toEqual([]);
            done();
          }
          else {
            event = event + 1;
          }
        }
      );

      const removeService1: IWSEvent = {
        model: 'Service',
        deleted: true,
        msg: {
          changed_fields: [],
          pk: 1,
          object: {
            id: 1,
            class_names: 'Service, XOSBase'
          }
        }
      };

      const removeService2: IWSEvent = {
        model: 'Service',
        deleted: true,
        msg: {
          changed_fields: [],
          pk: 2,
          object: {
            id: 2,
            class_names: 'Service, XOSBase'
          }
        }
      };

      const removeServiceDependency1: IWSEvent = {
        model: 'ServiceDependency',
        deleted: true,
        msg: {
          changed_fields: [],
          pk: 1,
          object: {
            id: 1,
            class_names: 'ServiceDependency, XOSBase'
          }
        }
      };

      const removeServiceInstnace1: IWSEvent = {
        model: 'VSGServiceInstance',
        deleted: true,
        msg: {
          changed_fields: [],
          pk: 1,
          object: {
            id: 1,
            class_names: 'VSGServiceInstance,TenantWithContainer,ServiceInstance'
          }
        }
      };

      subject_websocket.next(removeService1);
      subject_websocket.next(removeService2);
      subject_websocket.next(removeServiceDependency1);
      subject_websocket.next(removeServiceInstnace1);
      scope.$apply();
    });

    afterEach(() => {
      subscription.unsubscribe();
    });
  });

  describe(`the getModelType`, () => {
    it('should return the node type', () => {
      const res = service.getModelType(services[0]);
      expect(res).toBe('service');
    });

    it('should return the node type', () => {
      const res = service.getModelType(serviceInstances[0]);
      expect(res).toBe('serviceinstance');
    });
  });

  describe('the getNodeId method', () => {
    it('should return the id for a Service', () => {
      const res = service.getNodeId(services[0]);
      expect(res).toBe(`service~1`);
    });

    it('should return the id for a ServiceInstance', () => {
      const res = service.getNodeId(serviceInstances[0]);
      expect(res).toBe(`serviceinstance~1`);
    });
  });

  describe('the addNode method', () => {

    beforeEach(() => {
      spyOn(service.serviceGraph, 'setNode');
      spyOn(service.serviceGraph, 'setEdge');
    });

    it(`should a service to the graph`, () => {
      service.addNode(services[0]);
      expect(service.serviceGraph.setNode).toHaveBeenCalledWith('service~1', services[0]);
    });

    it('should add a service instance to the graph', () => {
      service.addNode(serviceInstances[0]);
      expect(service.serviceGraph.setNode).toHaveBeenCalledWith('serviceinstance~1', serviceInstances[0]);
    });

    it('should add an "ownership" edge to the graph', () => {
      service.addNode(serviceInstances[0]);
      expect(service.serviceGraph.setEdge).toHaveBeenCalledWith('serviceinstance~1', 'service~1', {service: 1, service_instance: 1, type: 'ownership'});
    });
  });

  describe('the addEdge method', () => {

    beforeEach(() => {
      spyOn(service.serviceGraph, 'setEdge');
    });

    it('should add a ServiceDependency to the graph', () => {
      service.addEdge(servicedependencies[0]);
      expect(service.serviceGraph.setEdge).toHaveBeenCalledWith('service~1', 'service~2', servicedependencies[0]);
    });

    it('should add a ServiceInstanceLink to the graph', () => {
      service.addEdge(serviceInstanceLinks[0]);
      expect(service.serviceGraph.setEdge).toHaveBeenCalledWith('serviceinstance~1', 'serviceinstance~2', serviceInstanceLinks[0]);
    });
  });

  describe('the nodesFromGraph and linksFromGraph methods', () => {
    let graph: Graph;

    beforeEach(() => {
      graph = new Graph();
      services.forEach(s => {
        graph.setNode(`service~${s.id}`, s);
      });

      servicedependencies.forEach(sd => {
        graph.setEdge('service~1', 'service~2', sd);
      });
    });

    it('should add id and type to the nodes', () => {
      const nodes = service.nodesFromGraph(graph);
      expect(nodes[0].id).toBe('service~1');
      expect(nodes[0].type).toBe('service');
      expect(nodes[0].data).toBeDefined();
    });

    it('should add id and type to the links', () => {
      const links = service.linksFromGraph(graph);
      expect(links[0].id).toBe('service~1-service~2');
      expect(links[0].type).toBe('servicedependency');
      expect(links[0].data).toBeDefined();
    });

    it('should handle ownership links', () => {
      graph.setNode(`serviceinstance~1`, serviceInstances[0]);
      graph.setEdge('service~1', 'serviceinstance~1', {type: 'ownership', service: 1, service_instance: 1});
      const links = service.linksFromGraph(graph);
      expect(links[1].source).toBe(0);
      expect(links[1].target).toBe(2);
    });

    it('should handle serviceinstancelink links', () => {
      graph.setNode(`serviceinstance~1`, serviceInstances[0]);
      graph.setNode(`serviceinstance~2`, serviceInstances[1]);
      graph.setEdge('serviceinstance~1', 'serviceinstance~2', serviceInstanceLinks[0]);
      const links = service.linksFromGraph(graph);
      const targetLink = _.find(links, {id: `serviceinstance~1-serviceinstance~2`});
      expect(targetLink).toBeDefined();
      expect(targetLink.source).toBe(3);
      expect(targetLink.target).toBe(2);
    });
  });

  describe('the addServiceInstance method', () => {
    beforeEach(() => {
      MockModelStore.query.calls.reset();
    });

    it('should add them to the graph', () => {
      service.addServiceInstances();
      expect(MockModelStore.query).toHaveBeenCalledWith(`ServiceInstance`, '/core/serviceinstances');
      expect(MockModelStore.query).toHaveBeenCalledWith(`ServiceInstanceLink`, '/core/serviceinstancelinks');
      expect(service.ServiceInstanceSubscription).toBeDefined();
      expect(service.ServiceInstanceLinkSubscription).toBeDefined();
      // TODO wait for the Observable to return and check the graph
    });
  });

  describe('the removeServiceInstance method', () => {
    beforeEach(() => {
      service.ServiceInstanceSubscription = {
        unsubscribe: jasmine.createSpy('ServiceInstanceSubscription')
      };
      service.ServiceInstanceLinkSubscription = {
        unsubscribe: jasmine.createSpy('ServiceInstanceLinkSubscription')
      };

      service.serviceGraph = new Graph();

      services.forEach(s => {
        service.addNode(s);
      });

      serviceInstances.forEach(si => {
        service.addNode(si);
      });

      serviceInstanceLinks.forEach(sil => {
        service.addEdge(sil);
      });
    });

    it('should cancel subscriptions', () => {
      service.removeServiceInstances();
      expect(service.ServiceInstanceSubscription.unsubscribe).toHaveBeenCalled();
      expect(service.ServiceInstanceLinkSubscription.unsubscribe).toHaveBeenCalled();
    });

    it('should remove ServiceInstance and related nodes/edges from the graph', () => {
      let filteredGraph = service.removeServiceInstances();
      expect(filteredGraph.nodes().length).toBe(2);
      expect(filteredGraph.edges().length).toBe(0);
      expect(service.serviceGraph.nodes().length).toBe(2);
      expect(service.serviceGraph.edges().length).toBe(0);
    });
  });
});
