import * as angular from 'angular';
import 'angular-mocks';
import 'angular-ui-router';
import {IXosServiceGraphStore, XosServiceGraphStore} from './graph.store';
import {Subject} from 'rxjs';
import {XosDebouncer} from '../../core/services/helpers/debounce.helper';
import {IXosServiceGraph} from '../interfaces';
import {XosServiceGraphExtender, IXosServiceGraphExtender} from './graph.extender';

let service: IXosServiceGraphStore, extender: IXosServiceGraphExtender;

const subjects = {
  service: new Subject<any>(),
  tenant: new Subject<any>(),
  subscriber: new Subject<any>(),
  network: new Subject<any>(),
  servicedependency: new Subject<any>()
};

// COARSE data
const coarseServices = [
  {
    id: 1,
    name: 'Service A',
    class_names: 'Service,PlCoreBase'
  },
  {
    id: 2,
    name: 'Service B',
    class_names: 'Service,PlCoreBase'
  }
];

const coarseTenants = [
  {
    id: 1,
    provider_service_id: 2,
    subscriber_service_id: 1,
    kind: 'coarse',
    class_names: 'Tenant,PlCoreBase'
  }
];

const mockModelStore = {
  query: (modelName: string) => {
    return subjects[modelName.toLowerCase()].asObservable();
  }
};

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

  beforeEach(() => {
    angular.module('xosServiceGraphStore', [])
      .service('XosServiceGraphStore', XosServiceGraphStore)
      .value('XosModelStore', mockModelStore)
      .service('XosServiceGraphExtender', XosServiceGraphExtender)
      .service('XosDebouncer', XosDebouncer);

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

  beforeEach(angular.mock.inject((
    XosServiceGraphStore: IXosServiceGraphStore,
    XosServiceGraphExtender: IXosServiceGraphExtender
  ) => {
    service = XosServiceGraphStore;
    extender = XosServiceGraphExtender;
  }));

  describe('when subscribing for the COARSE service graph', () => {
    beforeEach((done) => {
      subjects.service.next(coarseServices);
      subjects.servicedependency.next(coarseTenants);
      setTimeout(done, 500);
    });

    it('should return an observer for the Coarse Service Graph', (done) => {
      service.getCoarse()
        .subscribe(
          (res: IXosServiceGraph) => {
            expect(res.nodes.length).toBe(2);
            expect(res.nodes[0].d3Class).toBeUndefined();
            expect(res.links.length).toBe(1);
            expect(res.links[0].d3Class).toBeUndefined();
            done();
          },
          (err) => {
            done(err);
          }
        );
    });

    describe('when a reducer is register', () => {

      beforeEach((done) => {
        extender.register('coarse', 'test', (graph: IXosServiceGraph) => {
          graph.nodes = graph.nodes.map(n => {
            n.d3Class = `testNode`;
            return n;
          });

          graph.links = graph.links.map(n => {
            n.d3Class = `testLink`;
            return n;
          });

          return graph;
        });

        // triggering another next cycle to apply the reducer
        subjects.service.next(coarseServices);
        subjects.tenant.next(coarseTenants);
        setTimeout(done, 500);
      });

      it('should transform the result', (done) => {
        service.getCoarse()
          .subscribe(
            (res: IXosServiceGraph) => {
              expect(res.nodes.length).toBe(2);
              expect(res.nodes[0].d3Class).toEqual('testNode');
              expect(res.links.length).toBe(1);
              expect(res.links[0].d3Class).toEqual('testLink');
              done();
            },
            (err) => {
              done(err);
            }
          );
      });
    });
  });

  describe('when subscribing for the Fine-grained service graph', () => {
    xit('should have a test', () => {
      expect(true).toBeTruthy();
    });
  });
});
