
/*
 * 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
  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);
    }
    // else manually trigger the next with the last know value to trigger the subscribe method of who's requesting this data
    else {
      this.$log.debug(`[XosModelStore] QUERY: Calling "next" on: ${modelName}`);
      this.efficientNext(this._collections[modelName]);
    }

    // NOTE do we need to subscribe every time we query?
    this.webSocket.list()
      .filter((e: IWSEvent) => e.model === modelName)
      .subscribe(
        (event: IWSEvent) => {
          if (event.deleted) {
            this.storeHelpers.removeItemFromCollection(event, this._collections[modelName]);
          }
          else {
            this.storeHelpers.updateCollection(event, this._collections[modelName]);
          }
        },
        err => this.$log.error
      );

    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)
      .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);
        }
      );
  }
}
