import { Component, OnInit } from '@angular/core';
import {ApiService} from '../services/api.service';
import {TemplateModel} from '../models/template.model';
import {animate, style, transition, trigger} from '@angular/animations';
import {ValidationService} from '../services/validation.service';
import cloneDeep from 'lodash/cloneDeep';
import omit from 'lodash/omit';
import {DataService} from '../services/data.service';

@Component({
  selector: 'app-templates',
  templateUrl: './templates.component.html',
  styleUrls: ['./templates.component.scss'],
  animations: [
    trigger(
      'inOut', [
        transition(':enter', [
          style({height: 0, opacity: 0}),
          animate('0.5s ease-out', style({height: '*', opacity: 1}))
        ]),
        transition(':leave', [
          style({height: '*', opacity: 1}),
          animate('0.5s ease-in', style({height: 0, opacity: 0}))
        ])
      ]
    )
  ]
})
export class TemplatesComponent implements OnInit {

  collection = 'measurement';       // collection to view
  templates: TemplateModel[] = [];  // all templates of current collection
  templateGroups: {[first_id: string]: TemplateModel[]} = {};  // templates grouped by first_id
  templateEdit: {[first_id: string]: TemplateModel} = {};      // latest template of each first_id for editing
  groupsView: {  // grouped templates
    first_id: string,
    name: string,
    version: number,
    expanded: boolean,
    edit: boolean,
    entries: TemplateModel[]
  }[] = [];

  constructor(
    private api: ApiService,
    private validate: ValidationService,
    public d: DataService
  ) { }

  ngOnInit(): void {
    this.loadTemplates();
  }

  loadTemplates() {
    this.d.load(this.collection + 'Templates', () => {
      this.templates = this.d.arr[this.collection + 'Templates'];
      this.templateFormat();
    });
  }

  templateFormat() {
    this.templateGroups = {};
    this.templateEdit = {};
    this.templates.forEach(template => {  // group templates
      if (this.templateGroups[template.first_id]) {
        this.templateGroups[template.first_id].push(template);
      }
      else {
        this.templateGroups[template.first_id] = [template];
      }
    });
    Object.keys(this.templateGroups).forEach(id => {
      this.templateGroups[id] = this.templateGroups[id].sort((a, b) => a.version - b.version);
      this.templateEdit[id] = cloneDeep(this.templateGroups[id][this.templateGroups[id].length - 1]);
      this.templateEdit[id].parameters = this.templateEdit[id].parameters
        .map(e => {e.rangeString = JSON.stringify(e.range, null, 2); return e; });
    });
    this.groupsView = Object.values(this.templateGroups)
      .map(e => ({
        first_id: e[e.length - 1].first_id,
        name: e[e.length - 1].name,
        version: e[e.length - 1].version,
        expanded: false,
        edit: false,
        entries: e
      }));
  }

  saveTemplate(first_id) {
    const template = cloneDeep(this.templateEdit[first_id]);
    template.parameters = template.parameters.filter(e => e.name !== '');
    let valid = true;
    valid = valid && this.validate.string(template.name).ok;
    template.parameters.forEach(parameter => {
      valid = valid && this.validate.parameterName(parameter.name).ok;
      valid = valid && this.validate.parameterRange(parameter.rangeString).ok;
      if (valid) {
        parameter.range = JSON.parse(parameter.rangeString);
      }
    });
    if (valid) {
      const sendData = {name: template.name, parameters: template.parameters.map(e => omit(e, ['rangeString']))};
      if (first_id === 'null') {  // new template
        this.api.post<TemplateModel>(`/template/${this.collection}/new`, sendData, () => {
          delete this.d.arr[this.collection + 'Templates'];
          this.d.load(this.collection + 'Templates', () => {
            this.templates = this.d.arr[this.collection + 'Templates'];
            this.templateFormat();
          });
        });
      }
      else {
        this.api.put<TemplateModel>(`/template/${this.collection}/${template.first_id}`, sendData, () => {
          delete this.d.arr[this.collection + 'Templates'];
          this.d.load(this.collection + 'Templates', () => {
            this.templates = this.d.arr[this.collection + 'Templates'];
            this.templateFormat();
          });
        });
      }
    }
  }

  newTemplate() {
    if (!this.templateEdit.null) {
      const template = new TemplateModel();
      template.name = 'new template';
      this.groupsView.push({
        first_id: 'null',
        name: 'new template',
        version: 0,
        expanded: true,
        edit: true,
        entries: [template]
      });
      this.templateEdit.null = new TemplateModel();
    }
  }
}
