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


/// <reference path="../../../../typings/index.d.ts"/>
import * as _ from 'lodash';
import {BehaviorSubject, Observable} from 'rxjs/Rx';
import {IWSEvent, IWSEventService} from '../websocket/global';
import {IXosResourceService} from '../rest/model.rest';
import {IStoreHelpersService} from '../helpers/store.helpers';
import {IXosDebouncer} from '../../core/services/helpers/debounce.helper';
import {IXosModeldefsCache} from '../helpers/modeldefs.service';

export interface  IXosModelStoreService {
  query(model: string, apiUrl?: string): Observable<any>;
  get(model: string, id: string | number): Observable<any>;
  search(modelName: string): any[];
  clean(): void;
}

export class XosModelStore implements IXosModelStoreService {
  static $inject = [
    '$log',
    'WebSocket',
    'StoreHelpers',
    'ModelRest',
    'XosDebouncer',
    'XosModeldefsCache'
  ];

  private _collections: any; // NOTE contains a map of {model: BehaviourSubject}
  private efficientNext: any; // NOTE debounce next
  private _ws_subscriptions: any = {}; // NOTE contains a list of models that already subscribed to the WS obeservable

  constructor(
    private $log: ng.ILogService,
    private webSocket: IWSEventService,
    private storeHelpers: IStoreHelpersService,
    private ModelRest: IXosResourceService,
    private XosDebouncer: IXosDebouncer,
    private XosModeldefsCache: IXosModeldefsCache
  ) {
    this._collections = {};
    this.efficientNext = this.XosDebouncer.debounce(this.next, 500, this, false);
  }

  public clean() {
    this._collections = {};
  }

  public query(modelName: string, apiUrl?: string): Observable<any> {
    this.$log.debug(`[XosModelStore] QUERY: ${modelName}`);
    // if there isn't already an observable for that item
    // create a new one and .next() is called by this.loadInitialData once data are received
    if (!this._collections[modelName]) {
      this._collections[modelName] = new BehaviorSubject([]); // NOTE maybe this can be created when we get response from the resource
      this.loadInitialData(modelName, apiUrl);
    }

    if (!angular.isDefined(this._ws_subscriptions[modelName])) {
      // NOTE we need to subscribe to the WS observable only once
      const s = this.webSocket.list()
        .filter((e: IWSEvent) => e.model === modelName)
        .subscribe(
          (event: IWSEvent) => {
            this.$log.debug(`[XosModelStore] WS Event`, event);
            if (event.deleted) {
              this.storeHelpers.removeItemFromCollection(event, this._collections[modelName]);
            }
            else {
              this.storeHelpers.updateCollection(event, this._collections[modelName]);
            }
          },
          err => this.$log.error
        );
      this._ws_subscriptions[modelName] = s;
    }

    return this._collections[modelName].asObservable();
  }

  public search(modelName: string): any[] {
    try {
      const res =  _.reduce(Object.keys(this._collections), (results, k) => {
        let partialRes;
        // NOTE wrapped in a try catch as some subject may be errored, due to not available REST endpoint
        try {
          partialRes = _.filter(this._collections[k].value, i => {
            if (i && i.humanReadableName) {
              return i.humanReadableName.toLowerCase().indexOf(modelName) > -1;
            }
            else if (i && i.name) {
              return i.name.toLowerCase().indexOf(modelName) > -1;
            }
            return false;
          });
        } catch (e) {
          partialRes = [];
        }
        partialRes.map(m => {
          m.modelName = k;
          return m;
        });
        return results.concat(partialRes);
      }, []);
      return res;
    } catch (e) {
      return [];
    }
  }

  public get(modelName: string, modelId: string | number): Observable<any> {
    this.$log.debug(`[XosModelStore] GET: ${modelName} [${modelId}]`);
    const subject = new BehaviorSubject({});

    if (angular.isString(modelId)) {
      modelId = parseInt(modelId, 10);
    }

    this.query(modelName)
      .filter((res) => _.findIndex(res, {id: modelId}) > -1)
      .subscribe((res) => {
        const model = _.find(res, {id: modelId});
        if (model) {
          this.$log.debug(`[XosModelStore] GET: Calling "next" on: ${modelName} [${modelId}]`);
          subject.next(model);
        }
      });

    return subject.asObservable();
  }

  private next(subject: BehaviorSubject<any>): void {
    subject.next(subject.value);
  }

  private loadInitialData(model: string, apiUrl: string) {
    // TODO provide always the apiUrl together with the query() params
    if (!angular.isDefined(apiUrl)) {
      apiUrl = this.XosModeldefsCache.getApiUrlFromModel(this.XosModeldefsCache.get(model));
    }
    this.ModelRest.getResource(apiUrl).query().$promise
      .then(
        res => {
          this._collections[model].next(res);
        })
      .catch(
        err => {
          this._collections[model].error(err);
        }
      );
  }
}
