import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { Group } from '../../../shared/api/endpoints/models/group';
import { Drivers } from '../../../shared/api/endpoints/models/drivers';
import { GeneralInfo } from '../../../shared/api/endpoints/models/general-info';
import { Lastpos } from '../../../shared/api/endpoints/models/lastpos';
import { Sensor } from '../../../shared/api/endpoints/models/sensor';
import { Unit } from '../../../shared/api/endpoints/models/unit';
import { DataService } from '../../../shared/api/endpoints/services/data.service';
import { Phenomenon } from '../../../shared/api/endpoints/models/phenomenon';
import { SensorsService } from '../../../shared/api/endpoints/services/sensors.service';
import { ConfirmationService, MenuItem, MessageService } from 'primeng/api';
import { ManagementService } from '../../../shared/api/endpoints/services/management.service';
import { ToastService } from '../../../shared/services/toast.service';
import { map } from 'rxjs/operators';
import { HttpResponse } from '@angular/common/http';
import { AuthService } from '../../../auth/services/auth.service';
import { User } from '../../../auth/models/user';
import { SensorType } from '../../../shared/api/endpoints/models/sensor-type';
import { Subscription } from 'rxjs';

@Component({
  selector: 'unit-list',
  templateUrl: './unit-list.component.html',
  styleUrls: ['./unit-list.component.scss']
})
export class UnitListComponent implements OnInit, OnDestroy {

  @Input('user') loggedUser: User;
  @Input('units') units:
      Array<{ drivers?: Drivers; generalInfo?: GeneralInfo; holder?: any; lastpos?: Lastpos; sensors?: Array<Sensor>; unit?: Unit }>;

  phenomenons: Phenomenon[];
  sensorTypes: SensorType[];

  inProgress = true;
  items: MenuItem[] = [];
  position: 'bottom';
  groups: Group[];
  editedUnit: Unit;
  showEditUnitPopup = false;
  showInsertSensorPopup = false;
  showInsertPositionPopup = false;
  subscription: Subscription[] = [];

  constructor(
    private dataService: DataService,
    private sensorService: SensorsService,
    private confirmationService: ConfirmationService,
    private messageService: MessageService,
    private managementService: ManagementService,
    private toastService: ToastService,
    private authService: AuthService
  ) {
    this.initData();
  }

  ngOnInit(): void {
  }

  /**
   * Unsubscribe after leaving
   */
  ngOnDestroy(): void {
    this.subscription.forEach(subs => subs.unsubscribe());
  }

  /**
   * Get necessary data from backend
   */
  initData() {
    this.sensorService.getPhenomenons().subscribe(
      response => this.phenomenons = response
    );
  //  this.sensorService.getSensorTypes().subscribe(
  //    response => this.sensorTypes = response
  //  );
  //  this.setUser();
  //  this.getUnits();
  }

  /**
   * Get user from user state
   */
  setUser() {
    this.authService.getUserState().subscribe(res => {
      if (res) {
        this.loggedUser = res;
      }
    });
  }

  /**
   * Get all units and theirs sensors from backend
   */
  // getUnits() {
  //   this.dataService.getData().subscribe(data => {
  //     this.units = data;
  //     this.units.forEach(unit => unit.sensors.sort((a, b) => a.sensorId - b.sensorId));
  //   }, err => this.toastService.showError(err.error.message));
  // }

  /**
   * Show edit unit
   * @param $event click event
   * @param unit edited unit
   */
  editUnitPopup($event: MouseEvent, unit: Unit) {
    this.editedUnit = unit;
    this.showEditUnitPopup = true;
  }

  /**
   * Show insert unit
   * @param $event click event
   * @param unit unit for sensor insert
   */
  insertSensorPopup($event: any, unit: Unit) {
    this.showInsertSensorPopup = true;
    this.editedUnit = unit;
  }

  /**
   * Detele unit confirmation
   * @param $event click event
   * @param unit unit to delete
   */
  deleteUnit($event: any, unit: Unit) {
    this.confirmationService.confirm({
      message: 'Do you want to delete this unit?',
      header: 'Delete unit confirmation',
      icon: 'pi pi-info-circle',
      accept: () => {
        this.processUnitDeletion(unit);
      },
      reject: () => {
        this.toastService.operationRejected();
      },
      key: 'positionDialog'
    });
  }

  /**
   * Send delete unit request to backend
   * @param unit to delete
   */
  processUnitDeletion(unit: Unit) {
    this.managementService.deleteUnit$Response({
      body: {
        unit: {
          unit_id: unit.unitId
        }
      }
    }).pipe(
      map((response: HttpResponse<any>) => {
        if (response.status === 200) {
          this.toastService.showSuccessMessage(response.body.message);
          this.units = this.units.filter(testedUnit => testedUnit.unit.unitId !== unit.unitId);
        } else {
        }
      })
    ).toPromise().then().catch(err => this.toastService.showError(err.error.message));
  }

  /**
   * Show menu items to manipulate with unit
   * @param $event click event
   * @param unit unit we want edit
   */
  showItems($event: any, unit: Unit) {
    $event.stopPropagation();
    this.items = [
      {
        label: 'Edit unit', icon: 'pi pi-cog', command: () => {
          this.editUnitPopup($event, unit);
        }
      },
      {
        label: 'Insert position', icon: 'pi pi-cog', command: () => {
          this.insertPosition($event, unit);
        }
      },
      {
        label: 'Delete unit', icon: 'pi pi-times', command: () => {
          this.deleteUnit($event, unit);
        }
      },
      {
        label: 'Add sensor', icon: 'pi pi-cog', command: () => {
          this.insertSensorPopup($event, unit);
        }
      }
    ]
  }

  /**
   * Add created unit to memory so we do not need call backend
   * @param inserted unit
   */
  addUnit(inserted: any) {
    const sensors: Sensor[] = [];
    inserted.sensors.forEach(sens => {
      sensors.push({
        sensorId: sens.sensor_id,
        sensorType: sens.sensor_type,
        sensorName: sens.sensor_name,
        phenomenon: {
          phenomenonId: sens.phenomenon.phenomenon_id.toString()
        }
      })
    });
    this.units.push({
      unit: {
        unitId: inserted.unit.unit_id,
        description: inserted.unit.description
      },
      sensors
    })
  }

  /**
   * Add created sensors to unit in memory so we do not need call backend
   * @param inserted sensors
   */
  addSensors(inserted: any) {
    inserted.sensors.forEach(sens => {
      this.units.find(un => un.unit.unitId === inserted.unit.unit_id).sensors.push({
        sensorId: sens.sensor_id,
        sensorType: sens.sensor_type,
        sensorName: sens.sensor_name,
        phenomenon: {
          phenomenonId: sens.phenomenon.phenomenon_id.toString()
        }
      })
    });
  }

  /**
   * Delete sensor from memory
   * @param unitId sensor unit
   * @param sensor sensor to delete
   */
  deleteSensor(unitId: number, sensor: Sensor) {
    this.units.find(unit => unit.unit.unitId === unitId).sensors =
      this.units.find(unit => unit.unit.unitId === unitId).sensors.filter(testedSensor => testedSensor.sensorId !== sensor.sensorId);
  }

  /**
   * Show insert position popup
   * @param $event click event
   * @param unit unit to insert position for
   */
  insertPosition($event: any, unit: Unit) {
    $event.stopPropagation();
    this.showInsertPositionPopup = true;
    this.editedUnit = unit;
  }
}
