import { Component, Optional, OnInit } from '@angular/core';
import { MdDialogRef } from '@angular/material';

import { Responsibility } from '../../model/responsibility';
import { TerritoryResponsibility } from '../../model/territory-responsibility';
import { ResponsibilityService } from '../../services/responsibility.service';
import { SessionContext } from '../../common/session-context';
import { UserService } from '../../services/user.service';
import { BannerMessage } from '../../common/banner-message';
import { User } from '../../model/user';
import { BannerMessageStatusEn, ErrorType } from '../../common/enums';
import { MessageService, MessageDefines } from '../../services/message.service';

@Component({
  selector: 'app-shift-change',
  templateUrl: './shift-change.component.html',
  styleUrls: ['./shift-change.component.css']
})
export class ShiftChangeComponent implements OnInit {
  bannerMessageStatus = BannerMessageStatusEn;
  bannerMessage: BannerMessage = new BannerMessage();
  allRelevantUsers: User[]= new Array<User>();
  allUsers: User[]= new Array<User>();
  preSelectedUsers: User[] = new Array<User>();
  responsibilityContainers: TerritoryResponsibility[]= new Array<TerritoryResponsibility>();
  selectAll = false;
  isChangingShift = false;
  noUserSelected = true;
  shiftChangeFormInValid = true;
  isFetchingResp = false;
  dropdownSettings = {};


  constructor(
    @Optional() public dialogRef: MdDialogRef<ShiftChangeComponent>,
    private responsibilityService: ResponsibilityService,
    private messageService: MessageService,
    private userService: UserService,
    public sessionContext: SessionContext) { }

  ngOnInit() {
    this.getUsers();
  }

  afterUsersLoaded( ): void {
    this.getResponsibilities();

    this.dropdownSettings = {
      singleSelection: false,
      text: 'Vorauswahl Personen für Schichtübergabe',
      selectAllText: 'Alle Auswählen',
      unSelectAllText: 'Auswahl entfernen',
      enableSearchFilter: true,
      classes: 'custom-drop-down',
      badgeShowLimit: 2
    };
    this.checkIfPersonSelected();
  }

  getResponsibilities(): void {
    if ( !this.isFetchingResp ) {
      this.getMyResponsibilities();
    } else {
      this.getOtherResponsibilities();
    }
  }

    getMyResponsibilities(): void {
    const self = this;
    this.responsibilityService.getResponsibilities().subscribe(resps => setUIRespValues(resps),
      error => {
        console.log(error);
        this.messageService.emitError('Schichtübergabe getResponsibilities', ErrorType.retrieve);
      }
    );
    function setUIRespValues(resps: TerritoryResponsibility[]) {
      for (const responsibilityContainer of resps) {
        for (const responsibility of responsibilityContainer.responsibilityList) {
          for (const user of self.allUsers) {
            if (!self.preSelectedUsers.find(preSelUser => preSelUser.username === user.username)
              && responsibility.newResponsibleUser === user.username) {
              self.preSelectedUsers.push(user);
            }
          }
        }
      }
      self.responsibilityContainers = resps;      
    }
  }

  getOtherResponsibilities(): void {
    const self = this;
    this.responsibilityService.getAllResponsibilities().subscribe(resps => setUIRespValues(resps),
      error => {
        console.log(error);
        this.messageService.emitError('Schichtübergabe getResponsibilities', ErrorType.retrieve);
      }
    );
    function setUIRespValues(resps: TerritoryResponsibility[]) {
      self.responsibilityContainers = resps;      
    }
  }

  
  getResponsibilityAll(responsibilityContainer: TerritoryResponsibility, branchName: string) {
    return responsibilityContainer.responsibilityList.
      find(responsibility => responsibility.branchName === branchName);
  }

  getResponsiblity(responsibilityContainer: TerritoryResponsibility, branchName: string) {
    const resp: Responsibility = this.getResponsibilityAll( responsibilityContainer, branchName );
    if ( this.isFetchingResp && 
         resp && 
         resp.responsibleUser === this.allRelevantUsers[0].username) {
      return null;
    } else {
      return resp;
    }
  }


  getUsers() {
    if ( !this.isFetchingResp ) {
      this.getUsersExceptMe();
    } else {
      this.getUsersCurrentUser();
    }
  }

  private getUsersExceptMe() {
    const self = this;
    this.userService.getUsers().subscribe(resps => setUsers(resps),
      error => {
        console.log(error);
        this.messageService.emitError('Schichtübergabe getUsers', ErrorType.retrieve);
      }
    );
    function setUsers(_allUsers: User[]) {
      self.allUsers = _allUsers;
      self.allRelevantUsers = [];
      const currLoggedInUser = self.sessionContext.getCurrUser();

      for (const user of _allUsers) {
        if (currLoggedInUser.id !== user.id) {
          self.allRelevantUsers.push(user);
          user.itemName = user.name;
        }        
      }     
      self.afterUsersLoaded(); 
    }

  }

  private getUsersCurrentUser() {
    this.allRelevantUsers = [];
    this.allRelevantUsers.push(this.sessionContext.getCurrUser());
    this.preSelectedUsers = [];
    this.preSelectedUsers.push(this.sessionContext.getCurrUser());
    this.afterUsersLoaded(); 
  }

  cancelChange(): void {
    for (const responsibilityContainer of this.responsibilityContainers) {
      for (const responsibility of responsibilityContainer.responsibilityList) {
        responsibility.newResponsibleUser = '';
      }
    }
    this.shiftChange( false );
    
  }

  shiftChange( saveOrStornoYN: boolean ): void {
    const filteredResponsibilityContainers = this.responsibilityContainers;
    let foo: any;

    if ( this.isFetchingResp && saveOrStornoYN) {
      foo = this.responsibilityService.fetchResponsibilities(filteredResponsibilityContainers);
    } else {
      foo = this.responsibilityService.planResponsibilities(filteredResponsibilityContainers);      
    }

    foo.subscribe(resps => this.callbackSetResp(this, resps, saveOrStornoYN),
      error => {
        this.messageService.emitError('Schichtübergabe', ErrorType.update);
        this.dialogRef.close();
      }
    );
  }

  private callbackSetResp(self: ShiftChangeComponent , respCs: TerritoryResponsibility[], saveOrStornoYN: boolean) {
    if (respCs['ret'] && respCs['ret'] === 'OK') {
      self.dialogRef.componentInstance.isChangingShift = saveOrStornoYN;
      self.dialogRef.close();
    } else {
      const text = 'Ihre Verantwortlichkeiten haben sich geändert. ' +
              'Bitte prüfen Sie Ihre Eingaben und versuchen Sie es erneut.';
              self.messageService.emitInfo(text);
      this.responsibilityContainers = respCs;
    }
  }

  checkIfPersonSelected() {    
    this.shiftChangeFormInValid = true;
    for (const responsibilityContainer of this.responsibilityContainers) {
      for (const responsibility of responsibilityContainer.responsibilityList) {
        if (responsibility.newResponsibleUser !== '') {
          this.shiftChangeFormInValid = false;
          break;
        }
      }
    }        
  }

  isNewUserPresent( resp: Responsibility ): boolean {
    return resp != null && resp.newResponsibleUser != null && resp.newResponsibleUser !== '';

  } 
}
