import { Injectable } from '@angular/core';
import {TemplateModel} from '../models/template.model';
import {ApiService} from './api.service';
import {MaterialModel} from '../models/material.model';
import {BaseModel} from '../models/base.model';
import {UserModel} from '../models/user.model';
import {ModelItemModel} from '../models/model-item.model';
import {ModelFileModel} from '../models/model-file.model';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  constructor(
    private api: ApiService
  ) { }

  private collectionMap = {  // list of available collections
    materials: {path: '/materials?status[]=validated&status[]=new', model: MaterialModel, type: 'idArray'},
    materialSuppliers: {path: '/material/suppliers', model: null, type: 'idArray'},
    materialGroups: {path: '/material/groups', model: null, type: 'idArray'},
    materialTemplates: {path: '/template/materials', model: TemplateModel, type: 'template'},
    measurementTemplates: {path: '/template/measurements', model: TemplateModel, type: 'template'},
    conditionTemplates: {path: '/template/conditions', model: TemplateModel, type: 'template'},
    sampleNotesFields: {path: '/sample/notes/fields', model: TemplateModel, type: 'idArray'},
    users: {path: '/users', model: UserModel, type: 'idArray'},
    modelGroups: {path: '/model/groups', model: ModelItemModel, type: 'array'},
    modelFiles: {path: '/model/files', model: ModelFileModel, type: 'array'},
    user: {path: '/user', model: UserModel, type: 'string'},
    userKey: {path: '/user/key', model: BaseModel, type: 'string'}
  };

  arr: {[key: string]: any[]} = {};  // array of data
  latest: {[key: string]: any[]} = {};  // array of latest template versions
  id: {[key: string]: {[id: string]: any}} = {};  // data in format _id: data
  d: {[key: string]: any} = {};      // data not in array format

  contact = {name: 'CR/APS1-Lingenfelser', mail: 'dominic.lingenfelser@bosch.com'};  // global contact data

  load(collection, f = () => {}) {  // load data
    if (this.arr[collection]) { // data already loaded
      f();
    }
    else {  // load data
      this.api.get<any>(this.collectionMap[collection].path, data => {
        if (this.collectionMap[collection].type !== 'string') {  // array data
          this.arr[collection] = data
            .map(
              e => this.collectionMap[collection].model ?
                new this.collectionMap[collection].model().deserialize(e) : e
            );
          // load ids
          if (this.collectionMap[collection].type === 'idArray' || this.collectionMap[collection].type === 'template') {
            this.idReload(collection);
          }
        }
        else {  // not array data
          this.d[collection] = new this.collectionMap[collection].model().deserialize(data);
        }
        f();
      });
    }
  }

  // generate id object
  idReload(collection) {
    this.id[collection] = this.arr[collection].reduce((s, e) => {s[e._id] = e; return s; }, {});
    if (this.collectionMap[collection].type === 'template') {  // generate array with latest templates
      const tmpTemplates = {};
      this.arr[collection].forEach(template => {
        if (tmpTemplates[template.first_id]) {  // already found another version
          if (template.version > tmpTemplates[template.first_id].version) {
            tmpTemplates[template.first_id] = template;
          }
        }
        else {
          tmpTemplates[template.first_id] = template;
        }
      });
      this.latest[collection] = Object.values(tmpTemplates);
    }
  }
}
