import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {HttpResponse} from '@angular/common/http';
import {map} from 'rxjs/operators';
import {ManagementService} from '../../../api/endpoints/services/management.service';
import {ToastService} from '../../../services/toast.service';
import {InsertUnit} from '../../../api/endpoints/models/insert-unit';
import {InsertSensor} from '../../../api/endpoints/models/insert-sensor';
import {Phenomenon} from '../../../api/endpoints/models/phenomenon';
import {SensorsService} from '../../../api/endpoints/services/sensors.service';
import * as moment from 'moment-timezone';
import {SensorType} from '../../../api/endpoints/models/sensor-type';

@Component({
  selector: 'app-unit-insert-popup',
  templateUrl: './unit-insert-popup.component.html',
  styleUrls: ['./unit-insert-popup.component.scss']
})
export class UnitInsertPopupComponent implements OnInit {

  insertForm: UntypedFormGroup;
  items: UntypedFormArray;
  sensors = 0;

  @Input()phenomenons: Phenomenon[];
  @Input() isVisible;
  @Output() isVisibleChange: EventEmitter<boolean> = new EventEmitter<boolean>();
  @Output() emitNewUnit: EventEmitter<{unit: InsertUnit, sensors: InsertSensor[]}> =
    new EventEmitter<{unit: InsertUnit, sensors: InsertSensor[]}>()
  @Input() sensorTypes: SensorType[];

  constructor(
    private formBuilder: UntypedFormBuilder,
    private managementService: ManagementService,
    private toastService: ToastService,
    private sensorService: SensorsService
  ) {
    this.initForm();
  }

  ngOnInit(): void {
  }

  close() {
    this.isVisibleChange.emit(false);
  }

  initForm() {
    this.insertForm = this.formBuilder.group({
      unitId: ['', [Validators.required]],
      unitDescription: ['', Validators.required],
      lat: ['', [Validators.required, Validators.min(-90), Validators.max(90)]],
      lon: ['', [Validators.required, Validators.min(-180), Validators.max(180)]],
      sensors: this.formBuilder.array([])
    });
  }

  /**
   * Create formBuilder for sensor
   */
  createSensor(): UntypedFormGroup {
    return this.formBuilder.group({
      sensorId: ['', Validators.required],
      sensorName: ['', Validators.required],
      sensorType: ['null', Validators.required],
      phenomenons: ['null', Validators.required]
    });
  }

  /**
   * Add sensor to form
   */
  addSensor(): void {
    this.items = this.insertForm.get('sensors') as UntypedFormArray;
    this.items.push(this.createSensor());
    this.sensors++;
  }

  /**
   * Remove last sensor from form
   */
  removeSensor() {
    this.items = this.insertForm.get('sensors') as UntypedFormArray;
    this.items.removeAt(this.items.length - 1);
    this.sensors--;
  }

  /**
   * Clear form
   */
  clearFormArray() {
    const frmArray = this.insertForm?.get('sensors') as UntypedFormArray;
    if (frmArray) {
      frmArray.clear();
    }
    this.insertForm.reset();
  }

  /**
   * Insert unit with sensor and position if form valid
   */
  processInsertion() {
    if (this.insertForm.valid) {
      const lat = this.insertForm.controls.lat.value;
      const lon = this.insertForm.controls.lon.value;
      const unit: InsertUnit = {
        unit_id: this.insertForm.controls.unitId.value,
        description: this.insertForm.controls.unitDescription.value
      };
      const sensors: InsertSensor[] = [];
      const frmArray = this.insertForm?.get('sensors') as UntypedFormArray;

      // get sensors from form
      frmArray.controls.forEach(control => {
        const sensor: InsertSensor = {
          sensor_id: control.get('sensorId').value,
          sensor_name: control.get('sensorName').value,
          sensor_type: control.get('sensorType').value,
          phenomenon: {
            phenomenon_id: control.get('phenomenons').value
          },
        }
        sensors.push(sensor);
      });

      // insert unit
      this.managementService.insertUnit$Response({ body: { unit, sensors}}).pipe(
        map((response: HttpResponse<any>) => {
          if (response.status === 200) {
            // insert position
            this.sensorService.insertPosition$Response( {lat, lon, unit_id: this.insertForm.controls.unitId.value, date: moment().format('yyyy-MM-DD HH:mm:ssZZ')}).pipe(
              map((response2: HttpResponse<any>) => {
                if (response2.status === 200) {
                  this.toastService.showSuccessMessage('Unit ' + response.body.unitId + ' inserted!');
                  this.toastService.showSuccessMessage('Position to unit ' + response2.body.unitId + ' inserted!');
                  this.emitNewUnit.emit({unit, sensors});
                  this.close();
                } else {
                  this.toastService.showError('Unit insertion ' + response2.body.unitId + ' caused error! Wrong position!');
                  // if position not added delete unit
                  this.managementService.deleteUnit({body: {unit}}).toPromise().then().catch(
                    err => this.toastService.showError(err.error.message));
                }
              })
            ).toPromise().then().catch(err => this.toastService.showError(err.error.message));
          } else {
            this.toastService.showError('Unit insertion ' + response.body.unitId + ' caused error!');
          }
        })
      ).toPromise().then().catch(err => this.toastService.showError(err.error.message));
    }
  }
}
