
/*
 * 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 {IXosTableCfg} from '../../core/table/table';
import {IXosModelStoreService} from '../../datasources/stores/model.store';
import {IXosConfigHelpersService} from '../../core/services/helpers/config.helpers';
import * as _ from 'lodash';
import {IXosResourceService} from '../../datasources/rest/model.rest';
import {IStoreHelpersService} from '../../datasources/helpers/store.helpers';
import {IXosModelDiscovererService, IXosModel} from '../../datasources/helpers/model-discoverer.service';
import './crud.scss';
import {IXosCrudRelationService} from './crud.relations.service';
import {IXosDebugService, IXosDebugStatus} from '../../core/debug/debug.service';
import {IXosKeyboardShortcutService} from '../../core/services/keyboard-shortcut';
import {Subscription} from 'rxjs';
import {IXosModeldefsCache} from '../../datasources/helpers/modeldefs.service';

export interface IXosModelRelation {
  model: string;
  type: string;
  on_field: string;
}

class CrudController {
  static $inject = [
    '$scope',
    '$log',
    '$state',
    '$stateParams',
    'XosModelStore',
    'ConfigHelpers',
    'ModelRest',
    'StoreHelpers',
    'XosModelDiscoverer',
    'XosCrudRelation',
    'XosDebug',
    'XosKeyboardShortcut',
    'XosModeldefsCache'
  ];

  // bindings

  public data: {model: string};
  public tableCfg: IXosTableCfg;
  public formCfg: any;
  public baseUrl: string;
  public list: boolean;
  public modelName: string;
  public pluralTitle: string;
  public singularTitle: string;
  public tableData: any[];
  public model: any; // holds the real model
  public modelDef: IXosModel;
  public related: {manytoone: IXosModelRelation[], onetomany: IXosModelRelation[]} = {
    manytoone: [],
    onetomany: []
  };
  public relatedModels: {manytoone: any, onetomany: any} = {
    manytoone: {},
    onetomany: {}
  };
  public debugTab: boolean;

  private subscription: Subscription;

  constructor(
    private $scope: angular.IScope,
    private $log: angular.ILogService,
    private $state: angular.ui.IStateService,
    private $stateParams: ng.ui.IStateParamsService,
    private store: IXosModelStoreService,
    private ConfigHelpers: IXosConfigHelpersService,
    private ModelRest: IXosResourceService,
    private StoreHelpers: IStoreHelpersService,
    private XosModelDiscovererService: IXosModelDiscovererService,
    private XosCrudRelation: IXosCrudRelationService,
    private XosDebug: IXosDebugService,
    private XosKeyboardShortcut: IXosKeyboardShortcutService,
    private XosModeldefsCache: IXosModeldefsCache
  ) {
    this.$log.info('[XosCrud] Setup', $state.current.data);

    this.data = this.$state.current.data;
    this.modelDef = this.XosModeldefsCache.get(this.data.model);
    this.modelName = this.modelDef.verbose_name ? this.modelDef.verbose_name : this.modelDef.name;
    this.pluralTitle = this.ConfigHelpers.pluralize(this.modelName);
    this.singularTitle = this.ConfigHelpers.pluralize(this.modelName, 1);

    this.list = true;

    // TODO get the proper URL from model discoverer
    this.baseUrl = '#/' + this.modelDef.clientUrl.replace(':id?', '');

    this.tableCfg = this.modelDef.tableCfg;
    this.formCfg = this.modelDef.formCfg;

    // attach a redirect to the $save method
    const originalSave = this.formCfg.actions[0].cb;
    this.formCfg.actions[0].cb = (item, form: angular.IFormController) => {
      originalSave(item, form)
        .then(res => {
          this.$state.go(this.$state.current, {id: res.id});
        })
        .catch(err => {
          this.$log.error(`[XosCrud] Error while saving:`, item, err);
        });
    };

    this.debugTab = this.XosDebug.status.modelsTab;
    this.$scope.$on('xos.debug.status', (e, status: IXosDebugStatus) => {
      this.debugTab = status.modelsTab;
      this.$scope.$apply();
    });

    // if it is a detail page
    if ($stateParams['id']) {
      this.list = false;

      // if it is the create page
      if ($stateParams['id'] === 'add') {
        // generate a resource for an empty model
        const endpoint = this.XosModelDiscovererService.getApiUrlFromModel(this.XosModeldefsCache.get(this.data.model));
        const resource = this.ModelRest.getResource(endpoint);
        this.model = new resource({});
      }
      else {
        this.subscription = this.store.get(this.data.model, $stateParams['id'])
          .first(val => {
            // NOTE emit an event only if we have an object, and only the first time we have it
            return Object.keys(val).length > 0;
          })
          .subscribe(res => {
            $scope.$evalAsync(() => {
              this.related.onetomany = _.filter($state.current.data.relations, {type: 'onetomany'});
              this.related.manytoone = _.filter($state.current.data.relations, {type: 'manytoone'});
              this.model = res;
              this.getRelatedModels(this.related, this.model);
            });
          });
      }

      this.XosKeyboardShortcut.registerKeyBinding({
        key: 'A',
        cb: () => this.XosDebug.toggleDebug('modelsTab'),
        description: 'Toggle Debug tab in model details view'
      }, 'view');

      this.XosKeyboardShortcut.registerKeyBinding({
        key: 'delete',
        cb: () => {
          this.$state.go(this.$state.current.name, {id: null});
        },
        description: 'Go back to the list view'
      }, 'view');
    }
    // list page
    else {
      this.tableCfg.selectedRow = -1;

      this.XosKeyboardShortcut.registerKeyBinding({
        key: 'Tab',
        cb: () => this.iterateItems(),
        description: 'Iterate trough items in the list'
      }, 'view');

      this.XosKeyboardShortcut.registerKeyBinding({
        key: 'Enter',
        cb: () => {
          if (this.tableCfg.selectedRow < 0) {
            return;
          }
          this.$state.go(this.$state.current.name, {id: this.tableCfg.filteredData[this.tableCfg.selectedRow].id});
        },
        description: 'View details of selected item'
      }, 'view');

      this.XosKeyboardShortcut.registerKeyBinding({
        key: 'Delete',
        cb: () => {
          if (this.tableCfg.selectedRow < 0) {
            return;
          }
          const deleteFn = _.find(this.tableCfg.actions, {label: 'delete'});
          deleteFn.cb(this.tableCfg.filteredData[this.tableCfg.selectedRow]);
        },
        description: 'View details of selected item'
      }, 'view');

      // FIXME XosKeyboardShortcut modifiers does not look to work
      // this.XosKeyboardShortcut.registerKeyBinding({
      //   key: 'Tab',
      //   modifiers: ['alt'],
      //   cb: () => {
      //     this.tableCfg.selectedRow = -1;
      //   },
      //   description: 'Clear selected item'
      // }, 'view');

      this.subscription = this.store.query(this.data.model)
        .subscribe(
          (event) => {
            // NOTE Observable mess with $digest cycles, we need to schedule the expression later
            $scope.$evalAsync(() => {
              this.tableData = event;
            });
          }
        );
    }
  }

  $onDestroy() {
    this.subscription.unsubscribe();
    this.$log.info(`[XosCrud] Destroying component`);
  }

  public iterateItems() {
    const rowCount = this.tableCfg.filteredData.length > this.tableCfg.pagination.pageSize ? this.tableCfg.pagination.pageSize : this.tableCfg.filteredData.length;
    if ((this.tableCfg.selectedRow + 1) < rowCount) {
      this.tableCfg.selectedRow++;
    }
    else {
      this.tableCfg.selectedRow = 0;
    }
    this.$scope.$apply();
  }

  public getRelatedItemId(relation: IXosModelRelation, item: any): boolean {
    return this.XosCrudRelation.existsRelatedItem(relation, item);
  }

  public getHumanReadableOnField(r: IXosModelRelation) {
    return this.XosCrudRelation.getHumanReadableOnField(r, this.data.model);
  }

  public getRelatedModels(relations: {manytoone: IXosModelRelation[], onetomany: IXosModelRelation[]}, item: any) {
    this.$log.debug(`[XosCrud] Managing relation for ${this.data.model}:`, relations);

    // loading many to one relations (you'll get a model)
    _.forEach(relations.manytoone, (r: IXosModelRelation) => {
      if (!item || !item[`${r.on_field.toLowerCase()}_id`]) {
        return;
      }

      this.$log.debug(`[XosCrud] Loading manytoone relation with ${r.model} on ${r.on_field}`);

      if (!angular.isDefined(this.relatedModels.manytoone[r.model])) {
        this.relatedModels.manytoone[r.model] = {};
      }

      this.XosCrudRelation.getModel(r, item[`${r.on_field.toLowerCase()}_id`])
        .then(res => {
          this.relatedModels.manytoone[r.model][r.on_field] = res;
        })
        .catch(err => {
          this.$log.error(`[XosCrud] Error loading manytoone relation with ${r.model} on ${r.on_field}`, err);
        });
    });

    // loading onetomany relations (you'll get a list of models)
    _.forEach(relations.onetomany, (r: IXosModelRelation) => {
      if (!item) {
        return;
      }

      this.$log.debug(`[XosCrud] Loading onetomany relation with ${r.model} on ${r.on_field}`);

      if (!angular.isDefined(this.relatedModels.onetomany[r.model])) {
        this.relatedModels.onetomany[r.model] = {};
      }

      this.XosCrudRelation.getModels(r, item.id)
        .then(res => {
          this.relatedModels.onetomany[r.model][r.on_field] = res;
        })
        .catch(err => {
          this.$log.error(`[XosCrud] Error loading onetomany relation with ${r.model} on ${r.on_field}`, err);
        });
    });
  }
}

export const xosCrud: angular.IComponentOptions = {
  template: require('./crud.html'),
  controllerAs: 'vm',
  controller: CrudController
};
