import {Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewContainerRef, ViewEncapsulation} from '@angular/core';
import {
  CellCloseEvent,
  DataStateChangeEvent,
  GridComponent,
  GridDataResult,
  SelectableSettings,
  SelectionEvent
} from '@progress/kendo-angular-grid';
import {CompositeFilterDescriptor, SortDescriptor, toODataString} from '@progress/kendo-data-query';
import {LoanSummaryService} from '../service/loan_summary.service';
import {AuthService} from '../service/auth.service';
import {Observable} from 'rxjs';
import {Router} from '@angular/router';
import {LoanModel} from '../models/loan.model';
import {LoanSelectComponent} from '../loan-select/loan-select.component';
import {NotificationService, Type} from '@progress/kendo-angular-notification';
import {animate, style, transition, trigger} from '@angular/animations';

@Component({
  selector: 'app-list-all-loans',
  templateUrl: './list-all-loans.component.html',
  styleUrls: ['./list-all-loans.component.scss'],
  encapsulation: ViewEncapsulation.None,
  animations: [
    trigger('fadeIn', [
      transition(':enter', [
        style({ opacity: '0' }),
        animate('.5s ease-out', style({ opacity: '1'})),
      ]),
    ]),
    trigger('slideOutUp', [
      transition(':leave', [
        style({ opacity: '1' }),
        animate('.5s ease-out', style({ opacity: '0' })),
      ]),
    ]),
  ],
})
export class ListAllLoansComponent implements OnInit {
  public view: LoanSummaryService;
  public sort: Array<SortDescriptor> = [{dir: 'desc', field: 'Settlement'}];
  public filter: CompositeFilterDescriptor;
  public pageSize = 10;
  public skip = 0;
  @Output() LoanSelected: EventEmitter<LoanModel[]|LoanModel> = new EventEmitter<LoanModel[]|LoanModel>();

  @Input() EnableExportExcel = false;
  @Input() EnableExportPdf = false;
  @Input() EnableSelectButton = false;
  @Input() MaxSelect = 1;
  @Input() Preselect: LoanModel[] = [];
  public SelectedLoans: LoanModel[] = [];
  public selectableSettings: SelectableSettings|boolean;
  private privateSingleSelection = true;
  public gridSelection: string[] = [];
  @ViewChild(GridComponent, { static: true  }) public grid: GridComponent;
  @ViewChild(GridComponent, { read:  ViewContainerRef  }) public gridVR: ViewContainerRef;


  constructor(private service: LoanSummaryService,
              private auth: AuthService,
              private router: Router,
              private notificationService: NotificationService) { }

  public ngOnInit(): void {
    // Bind directly to the service as it is a Subject
    this.view = this.service;

    // Fetch the data with the initial state
    this.loadData();

    // selectable
    this.setSelectableSettings();

    // Preselect on Init only
    this.Preselect.forEach( v => {
      if ( v !== undefined && v !== null && v.Id !== '' ){
        this.AddLoanToSelection(v);
        this.gridSelection.unshift(v.Id);
      }
    });
  }

  @Input() set SingleSelection(single: boolean) {
    this.privateSingleSelection = single;
    this.setSelectableSettings();
  }

  get SingleSelection(): boolean{
    return this.privateSingleSelection;
  }

  public setSelectableSettings(): void {
    this.privateSingleSelection = this.MaxSelect === 1;
    if ( this.EnableSelectButton ){
        this.selectableSettings = {
          checkboxOnly: true,
          mode: this.privateSingleSelection ? 'single' : 'multiple',
          drag: false,
      };
    }else{
      this.selectableSettings = false;
    }
  }

  public dataStateChange({ skip, take, sort, filter }: DataStateChangeEvent): void {
    // Save the current state of the Grid component
    this.skip = skip;
    this.pageSize = take;
    this.sort = sort;
    this.filter = filter;

    // Reload the data with the new state
    this.loadData();

    // Expand the first row initially
    // this.grid.expandRow(0);
  }

  public filterChange(filter: CompositeFilterDescriptor): void {
    this.filter = filter;
    console.log(filter);
  }
  private loadData(): void {
    this.service.query({ skip: this.skip, take: this.pageSize, sort: this.sort, filter: this.filter});
  }

  private photoURL(peopleId: any): string {
    const url = this.auth.getUrl('avatar/') + peopleId;
    return 'url("' + url + '")';
  }

  public allowEdit(): boolean {
    return this.auth.allowEditLoan();
  }

  public allData = (): Observable<GridDataResult> => {
    return this.service.queryAll({skip: 0, take: 999999, sort: this.sort, filter: this.filter});
  }

  public onCellClick(event: CellCloseEvent): void {
   //  this.LoanSelected.emit(event.dataItem);
  }

  public AddLoanToSelection(loan: LoanModel): void{
    const idx = this.SelectedLoans.findIndex( v => {
      return v.Id === loan.Id;
    });
    if ( idx === -1 ) { // not found
      this.SelectedLoans.unshift(loan);
    }
  }

  public onFinishSelection(): void{
    if ( this.MaxSelect === 1 ){
      this.LoanSelected.emit(this.SelectedLoans[0]);
    }else{
      this.LoanSelected.emit(this.SelectedLoans);
    }

    console.log('loan selected', this);
    this.notifyUser('ended');
  }

  public RemoveFromSelection(l: LoanModel): void{
    this.SelectedLoans = this.SelectedLoans.filter(  v =>  l.Id !== v.Id  );
    this.gridSelection = this.gridSelection.filter(  v => v !== l.Id );
  }

  public onSelectionChange(sel: SelectionEvent): void {
    // to avoid race condition, we do action after 200ms
    setTimeout( () => {
      sel.deselectedRows.forEach(v => {
        this.RemoveFromSelection(v.dataItem);
      });

      sel.selectedRows.forEach(v => {
        if ( this.SelectedLoans.length < this.MaxSelect) {
          this.AddLoanToSelection(v.dataItem);
        }else{
          // remove those that was added by grid selection
          this.gridSelection = this.gridSelection.filter( existing =>  existing !== v.dataItem.Id );
          this.notifyUser('Maximum selection reached', { style: 'warning', icon: true });
        }
      });
    }, 200);
  }

  public notifyUser( msg: string, lookAndFeel?: Type): void {
    if (lookAndFeel === undefined ){
      lookAndFeel = { style: 'success', icon: true };
    }
    this.notificationService.show({
      appendTo: this.gridVR,
      content: msg,
      cssClass: 'button-notification',
      animation: { type: 'slide', duration: 400 },
      position: { horizontal: 'right', vertical: 'top' },
      type: lookAndFeel,
      closable: false,
      hideAfter: 5000,
    });
  }
}
