import { Component, OnInit, Optional, QueryList } from '@angular/core';
import { MdDialogRef } from '@angular/material';
import { DaterangepickerConfig } from 'ng2-daterangepicker';
import { NotificationService } from '../../services/notification.service';
import { User } from '../../model/user';
import { Notification } from '../../model/notification';
import { Status } from '../../model/status';
import { Branch } from '../../model/branch';
import { GridTerritory } from '../../model/gridterritory';
import { FilterMatrix } from '../../model/controller-model/filter-matrix';
import { TerritoryResponsibility } from '../../model/territory-responsibility';
import { AbstractListComponent } from '../../lists/abstract-list/abstract-list.component';
import { SessionContext } from '../../common/session-context';
import { BannerMessage } from '../../common/banner-message';
import { StatusEn, BannerMessageStatusEn, ErrorType } from '../../common/enums';
import { FormattedTimestampPipe } from '../../common-components/pipes/formatted-timestamp.pipe';
import { MessageService } from '../../services/message.service';
@Component({
  selector: 'app-entry',
  templateUrl: './entry.component.html',
  styleUrls: ['./entry.component.css']
})
export class EntryComponent implements OnInit {
  private originalNotification: Notification;

  isEditDialog = false;
  isReadOnlyDialog = false;
  isInstructionDialog = false;
  user: User = null;
  notification: Notification = new Notification();
  selectedStatusId: number;
  notificationVersion: Notification = new Notification();
  notificationVersions: Notification[];
  gridTerritories: GridTerritory[];
  branches: Branch[];
  statuses: Status[];
  defaultBranch = '';
  defaultGridTerritory = '';

  constructor(
    public dialogRef: MdDialogRef<EntryComponent>,
    private daterangepickerConfig: DaterangepickerConfig,
    private notificationService: NotificationService,
    public sessionContext: SessionContext,
    private messageService: MessageService) {
  }

  ngOnInit() {
    this.gridTerritories = this.sessionContext.getMasterGridTerritories();
    this.branches = this.sessionContext.getBranches();
    this.statuses = this.sessionContext.getStatuses();
    this.user = this.sessionContext.getCurrUser();

    this.daterangepickerConfig.settings = {
      timePicker: true,
      timePicker24Hour: true,
      timePickerSeconds: false,
      timePickerIncrement: 1,
      useCurrent: true,
      drops: 'up',
      locale: {
        format: 'DD.MM.YYYY HH:mm',
        applyLabel: '&Uuml;bernehmen',
        cancelLabel: 'Abbrechen',
        daysOfWeek: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
        monthNames: ['Januar', 'Februar', 'M&auml;rz', 'April', 'Mai', 'Juni', 'Juli',
          'August', 'September', 'Oktober', 'November', 'Dezember'],
        firstDay: 1
      }
    };

    if (!this.notification.beginDate) {
      this.notification.beginDate = this.getCurrentDateTime();
    }

    if (!this.notification.createUser) {
      this.notification.createUser = this.user.name;
    }

    if (!this.notification.fkRefBranch && !this.isEditDialog) {
      this.defaultBranch = this.getUniqueBranchNameForUser(
        this.sessionContext.getfilterMatrix().responsibilityContainerMatrix,
        this.sessionContext.getCurrUser().username);
      const branchTmp = this.branches.filter((b) => b.name === this.defaultBranch)[0];
      if (branchTmp) {
        this.notification.fkRefBranch = branchTmp.id;
      }
    }

    if (!this.notification.fkRefGridTerritory && !this.isEditDialog) {
      this.defaultGridTerritory = this.getUniqueGridTerritoryNameForUser(
        this.sessionContext.getfilterMatrix().responsibilityContainerMatrix,
        this.sessionContext.getCurrUser().username);
      const gridTerritoryTmp = this.sessionContext.getGridTerritories().filter((gt) => gt.description === this.defaultGridTerritory)[0];
      if (gridTerritoryTmp) {
        this.notification.fkRefGridTerritory = gridTerritoryTmp.id;
      }
    }
  }

  onNotificationVersionChange(version: number) {
    this.notification = this.notificationVersions.find(notification => Number(notification.version) === Number(version));
  }

  setNotification(notification: Notification) {
    this.originalNotification = notification;
    this.notification = Object.assign(new Notification(), notification);
    this.notificationVersion = notification;
    if (!this.notification.beginDate) {
      this.notification.beginDate = this.getCurrentDateTime();
    }

    this.notificationService.getNotificationVersions(notification.incidentId).subscribe(notes => this.notificationVersions = notes,
      error => {
        this.messageService.emitError('Versionen', ErrorType.retrieve);
        this.dialogRef.close();
      }
    );
  }

  edit() {
    this.notification.responsibilityControlPoint = this.user.name;
    const notificationClone = Object.assign(new Notification(), this.notification);
    notificationClone.decoratorNotificationVersions = undefined;

    this.notificationService.updateNotification(notificationClone).subscribe(result => this.dialogRef.close(),
      error => {
        this.messageService.emitError('Eintrag', ErrorType.update);
        this.dialogRef.close();
      });
  }

  add(adminFlag: boolean) {
    this.notification.responsibilityControlPoint = this.user.name;
    this.notification.adminFlag = adminFlag;
    this.notificationService.createNotification(this.notification).subscribe(result => this.dialogRef.close(),
      error => {
        this.messageService.emitError('Eintrags', ErrorType.create);
        this.dialogRef.close();
      });
  }

  cancel() {
    this.dialogRef.close();
  }

  statusChanged(statusId: number, notification: Notification) {
    const statusIdNum: number = Number(statusId);
    if (statusIdNum === StatusEn.done || statusIdNum === StatusEn.closed) {
      notification.finishedDate = this.getCurrentDateTime();
    } else {
      notification.finishedDate = null;
    }
  }

  getCurrentDateTime() {
    return new Date().toISOString();
  }

  getUniqueBranchNameForUser(responsibilityContainerMatrix: TerritoryResponsibility[], currentUserName: string): string {
    let uniqueBranchName = '';
    let branchNames: string[] = [];

    responsibilityContainerMatrix.forEach((gridTerritory) => {
      gridTerritory.responsibilityList.forEach((responsibility) => {
        if (responsibility.responsibleUser === currentUserName) {
          branchNames.push(responsibility.branchName);
        }
      });
    });

    branchNames = branchNames.filter((item, pos, ar) => ar.indexOf(item) === pos);

    if (branchNames.length === 1) {
      uniqueBranchName = branchNames[0];
    } else {
      uniqueBranchName = '';
    }

    return uniqueBranchName;
  }


  getUniqueGridTerritoryNameForUser(responsibilityContainerMatrix: TerritoryResponsibility[], currentUserName: string): string {
    let uniqueGridTerritoryName = '';
    let gridTerritoryNames: string[] = [];
    const gridTerritories = this.sessionContext.getGridTerritories();

    responsibilityContainerMatrix.forEach((gridTerritory) => {
      gridTerritory.responsibilityList.forEach((responsibility) => {
        if (responsibility.responsibleUser === currentUserName) {
          const gtTmp = gridTerritories.filter(
            (gt) => gt.description === gridTerritory.gridTerritoryDescription)[0];
          if (gtTmp) {
            const masterGridTerritoryID = gtTmp.fkRefMaster;
            const masterGridTerritory = gridTerritories.filter((mGT) => mGT.id === masterGridTerritoryID)[0];
            gridTerritoryNames.push(masterGridTerritory.description);
          }
        }
      });
    });

    gridTerritoryNames = gridTerritoryNames.filter((item, pos, ar) => ar.indexOf(item) === pos);

    if (gridTerritoryNames.length === 1) {
      uniqueGridTerritoryName = gridTerritoryNames[0];
    } else {
      uniqueGridTerritoryName = '';
    }
    return uniqueGridTerritoryName;
  }
}
