
/*
 * 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 angular from 'angular';
import 'angular-mocks';
import 'angular-resource';
import {IXosModelStoreService, XosModelStore} from './model.store';
import {Subject} from 'rxjs';
import {IWSEvent} from '../websocket/global';
import {StoreHelpers} from '../helpers/store.helpers';
import {ModelRest} from '../rest/model.rest';
import {ConfigHelpers} from '../../core/services/helpers/config.helpers';
import {AuthService} from '../rest/auth.rest';
import {XosDebouncer} from '../../core/services/helpers/debounce.helper';
import {IXosModeldefsCache} from '../helpers/modeldefs.service';
import {XosFormHelpers} from '../../core/form/form-helpers';

let service: IXosModelStoreService;
let httpBackend: ng.IHttpBackendService;
let $scope;
let WebSocket;
let XosModeldefsCache;

class MockWs {
  private _list;
  constructor() {
    this._list = new Subject<IWSEvent>();
  }
  list() {
    return this._list.asObservable();
  }

  next(event: IWSEvent) {
    this._list.next(event);
  }
}

const queryData = [
  {id: 1, name: 'foo'},
  {id: 2, name: 'bar'}
];

const MockAppCfg = {
  apiEndpoint: 'http://xos-test:3000/api',
  websocketClient: 'http://xos-test:3000'
};

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

  beforeEach(() => {
    angular
      .module('ModelStore', ['ngResource', 'toastr', 'ngCookies'])
      .service('WebSocket', MockWs)
      .service('StoreHelpers', StoreHelpers) // TODO mock
      .service('ModelRest', ModelRest) // TODO mock
      .service('XosModelStore', XosModelStore)
      .service('ConfigHelpers', ConfigHelpers) // TODO mock
      .service('AuthService', AuthService)
      .service('XosFormHelpers', XosFormHelpers)
      .constant('AppConfig', MockAppCfg)
      .value('XosModeldefsCache', {
        get: jasmine.createSpy('XosModeldefsCache.get').and.returnValue({}),
        getApiUrlFromModel: jasmine.createSpy('XosModeldefsCache.getApiUrlFromModel')
      })
      .service('XosDebouncer', XosDebouncer);

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

  beforeEach(angular.mock.inject((
    XosModelStore: IXosModelStoreService,
    $httpBackend: ng.IHttpBackendService,
    _$rootScope_: ng.IRootScopeService,
    _WebSocket_: any,
    _XosModeldefsCache_: IXosModeldefsCache
  ) => {
    service = XosModelStore;
    httpBackend = $httpBackend;
    $scope = _$rootScope_;
    WebSocket = _WebSocket_;
    XosModeldefsCache = _XosModeldefsCache_;

    // ModelRest will call the backend
    httpBackend.whenGET(`${MockAppCfg.apiEndpoint}/core/samples`)
      .respond(queryData);
  }));

  describe('the QUERY method', () => {
    it('should return an Observable', () => {
      expect(typeof service.query('test').subscribe).toBe('function');
    });

    it('the first event should be the resource response', (done) => {
      XosModeldefsCache.getApiUrlFromModel.and.returnValue(`/core/samples`);
      let event = 0;
      service.query('sample')
        .subscribe(collection => {
          event++;
          if (event === 2) {
            expect(collection[0].id).toEqual(queryData[0].id);
            expect(collection[1].id).toEqual(queryData[1].id);
            done();
          }
        });
      $scope.$apply();
      httpBackend.flush();
    });
  });

  describe('the GET method', () => {
    it('should return an observable containing a single model', (done) => {
      let event = 0;
      XosModeldefsCache.getApiUrlFromModel.and.returnValue(`/core/samples`);
      service.get('sample', queryData[1].id)
        .subscribe((model) => {
          event++;
          if (event === 2) {
            expect(model.id).toEqual(queryData[1].id);
            expect(model.name).toEqual(queryData[1].name);
            done();
          }
        });
      httpBackend.flush();
      $scope.$apply();
    });
  });

  describe('when a web-socket event is received for that model', () => {
    it('should update the collection', (done) => {
      let event = 0;
      service.query('sample', '/core/samples')
        .subscribe(
          collection => {
            event++;
            if (event === 3) {
              expect(collection[0].id).toEqual(queryData[0].id);
              expect(collection[1].id).toEqual(queryData[1].id);
              expect(collection[2].id).toEqual(3);
              expect(collection[2].name).toEqual('baz');
              done();
            }
          },
          err => {
            done(err);
          }
        );
      window.setTimeout(() => {
        WebSocket.next({
          model: 'sample',
          msg: {
            changed_fields: ['id'],
            object: {id: 3, name: 'baz'},
            pk: 3
          }
        });
      }, 1);
      $scope.$apply();
      httpBackend.flush();
    });
  });

  describe('when multiple stores are requested', () => {

    beforeEach(() => {
      httpBackend.expectGET(`${MockAppCfg.apiEndpoint}/core/firsts`)
        .respond([
          {first: 'foo'}
        ]);
      httpBackend.expectGET(`${MockAppCfg.apiEndpoint}/core/seconds`)
        .respond([
          {second: 'foo'}
        ]);
    });
    it('should create different Subject', (done) => {
      let fevent = 0;
      let sevent = 0;
      XosModeldefsCache.get.and.callFake(v => v);
      XosModeldefsCache.getApiUrlFromModel.and.callFake(v => `/core/${v}s`);
      service.query('first')
        .subscribe(first => {
          fevent++;
          if (fevent >= 2) {
            service.query('second')
              .subscribe(second => {
                sevent++;
                if (sevent === 2) {
                  expect(first).not.toEqual(second);
                  done();
                }
              });
          }
        });
      $scope.$apply();
      httpBackend.flush();
    });
  });
});
