import {Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
import {PayInModel} from '../models/pay-in.model';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {PayInListFilterModel} from '../models/pay-in-list.filter.model';
import {PayInService} from '../service/pay-in.service';
import {PayInListResult} from '../models/pay-in-list-result.model';
import {Router} from '@angular/router';
import {PopupIncomeFilterComponent} from '../popup-income-filter/popup-income-filter.component';
import {PageChangeEvent, SortSettings} from '@progress/kendo-angular-grid';
import {SortDescriptor} from '@progress/kendo-data-query';
import {UploadMetaModel} from '../models/uploadMetaModel';
import {debounce} from 'ts-debounce';
import {LoanModel} from '../models/loan.model';
import {LoanSingleService} from '../service/loan.single.service';
import {PayInModelEx} from '../models/pay-in-ex.model';




@Component({
  selector: 'app-pay-in',
  templateUrl: './pay-in.component.html',
  styleUrls: ['./pay-in.component.scss']
})
export class PayInComponent implements OnInit {
  @Input() allowAddNew = true;
  @Input() allowEdit = true;
  @Input() showLoanColumn = true;
  @Input() showUploadColumn = true;
  private filterUploadMeta: UploadMetaModel = new UploadMetaModel({});
  public filterLoan = new LoanModel({});
  @Input() filter: PayInListFilterModel = new PayInListFilterModel({});
  @Output() errorOccurred = new EventEmitter<string>();
  @ViewChild('filterDialog', {static: true}) filterDialog: PopupIncomeFilterComponent;
  private privateLoadDataNow = false;


  public gridData: PayInListResult = { data: [], total: 0};
  public incomeFormGroup: FormGroup;
  public editedRowIndex: number;

  public showBalance = true;
  public showOffsetBalance = true;

  public pageable = true;
  public sortable: SortSettings = {
    mode: 'single'
  };

  public loading = false;
  private debouncedLoadFilteredData = () => {};

  constructor(private pis: PayInService, private lss: LoanSingleService, private router: Router) { }

  ngOnInit(): void {
    this.debouncedLoadFilteredData = debounce(this.loadFilteredData, 500);
    if (this.privateLoadDataNow) { // not in delayed loading mode
      this.debouncedLoadFilteredData();
    }
  }

  public loadFilteredData(): void{
    this.loading = true;
    this.pis.getPayInList(this.filter).subscribe(
      ( resp: PayInListResult) => {
        this.gridData.total = resp.total;
        this.gridData.data = [];
        resp.data.forEach(v => {
          this.gridData.data.push(new PayInModelEx(v));
        });
        this.loading = false;
      }, err => {
        this.loading = false;
      }, () => {
        this.loading = false;
      }
    );
  }

  // Upload Filter
  @Input() set uploadMeta(value: UploadMetaModel) {
    this.filterUploadMeta = value;
    if ( value.Id <= 0 ) {
      this.filter.UploadIds = [];
    } else{
      this.filter.UploadIds = [ value.Id.toString() ];
    }
    this.debouncedLoadFilteredData();
    console.log('upload filter changed', value, this.filter);
  }

  get uploadMeta(): UploadMetaModel {
    return this.filterUploadMeta;
  }

  // LoanId filter
  @Input() set Loan(value: LoanModel){
    this.filterLoan = value;
    if ( value.Id === '' ) {
      this.filter.LoanIds = [];
    }else{
      this.filter.LoanIds = [ value.Id ];
    }
    this.debouncedLoadFilteredData();
    console.log('filter loanId changed', value, this.filter);
  }

  get Loan(): LoanModel {
    return this.filterLoan;
  }

  @Input()  set LoadDataNow( value: boolean) {

    if ( value === true && this.privateLoadDataNow === false) {
      this.debouncedLoadFilteredData();
    }
    this.privateLoadDataNow = value;
  }
  get LoadDataNow(): boolean {
    return this.privateLoadDataNow;
  }

  public addHandler({ sender }): void  {
    this.closeEditor(sender);

    const balance = -1;
    const offsetBalance = -1;
    this.showBalance = balance >= 0 ;
    this.showOffsetBalance = offsetBalance >= 0 ;
    this.incomeFormGroup = this.createFormGroup(new PayInModelEx({}));

    console.log(this.incomeFormGroup);
    sender.addRow(this.incomeFormGroup);
  }

  private createFormGroup(dataItem: PayInModelEx): FormGroup {
    const Loan = this.filterLoan.Id !== '' ? this.filterLoan : dataItem.Loan;
    const UploadMeta = this.filterUploadMeta.Id !== 0 ? this.filterUploadMeta : dataItem.UploadMeta ;

    return new FormGroup({
      Id: new FormControl({value: dataItem.Id, disabled: true}, Validators.required),
      Lender: new FormControl(dataItem.Lender),
      Amount: new FormControl(dataItem.Amount),
      LoanNumber: new FormControl(dataItem.LoanNumber),
      IncomeAmount: new FormControl(dataItem.IncomeAmount, Validators.required),
      IncomeType: new FormControl(dataItem.IncomeType, Validators.required),
      Ts: new FormControl(dataItem.Ts, Validators.required),
      Balance: new FormControl(dataItem.Balance, Validators.required),
      OffsetBalance: new FormControl(dataItem.OffsetBalance, Validators.required),
      Loan: new FormControl(Loan),
      UploadMeta: new FormControl(UploadMeta)
    });
  }

  public editHandler({ sender, rowIndex, dataItem }): void {
    this.closeEditor(sender);

    this.showBalance = dataItem.Balance >= 0 ;
    this.showOffsetBalance = dataItem.OffsetBalance >= 0 ;
    this.incomeFormGroup = this.createFormGroup(dataItem);
    this.editedRowIndex = rowIndex;
    sender.editRow(rowIndex, this.incomeFormGroup);

  }

  public cancelHandler({ sender, rowIndex }): void {
    console.log(sender);
    this.closeEditor(sender, rowIndex);
  }

  public saveHandler({ sender, rowIndex, formGroup, isNew }): void {
    const v = formGroup.getRawValue();

    if ( !this.showBalance) { v.Balance = -1; }
    if ( !this.showOffsetBalance) { v.OffsetBalance = -1; }

    const pi = this.buildPayInForSave(v, isNew);
    this.lss.savePayIn(pi, isNew).subscribe(
      (resp: PayInModelEx) => {
        this.Loan.cuPayIn( new PayInModel(resp));
        this.updatePiInGrid(new PayInModelEx(resp));
      },
      err => {
        // TODO: this.errorOccurred.emit('Error saving Income');
      }
    );
    sender.closeRow(rowIndex);
  }

  private buildPayInForSave(v: any, isNew: boolean): PayInModel {
    const pi = new PayInModel({});
    if ( isNew ) { pi.Id = 0; }

    // are we using filtered loan?
    let loan = v.Loan;

    if (loan === null || this.filterLoan !== undefined && this.filterLoan.Id !== '') {
      loan = this.filterLoan;
    }

    pi.Id = v.Id;
    pi.Amount = loan.Amount;
    pi.Balance = v.Balance;
    pi.Lender = loan.Id === '' ? v.Lender : loan.Lender;
    pi.LoanId = loan.Id;
    pi.LoanNumber = loan.LenderLoanNumber;
    pi.OffsetBalance = v.OffsetBalance;
    pi.Settlement = loan.Settlement;
    pi.IncomeAmount = v.IncomeAmount;
    pi.IncomeType = v.IncomeType;
    pi.UploadId = this.filterUploadMeta.Id;
    pi.Ts = v.Ts;
    return pi;
  }

  private updatePiInGrid(pi: PayInModel): void {
    const notFound = this.gridData.data.every( v => {
      if ( v.Id === pi.Id ){
        Object.assign(v, pi);
        return false;
      }
      return true;
    });

    if ( notFound ) {
      this.gridData.data.unshift(pi);
    }
  }

  public removeHandler({ dataItem }): void {
    console.log('delete', dataItem);

    this.Loan.PayIn = this.Loan.PayIn.filter(v => v.Id !== dataItem.Id  );
    this.gridData.data = this.gridData.data.filter(v =>   v.Id !== dataItem.Id) ;

    this.lss.removePayIn(dataItem.Id);
  }

  private closeEditor(grid, rowIndex = this.editedRowIndex): void{
    grid.closeRow(rowIndex);
    this.editedRowIndex = undefined;
    this.incomeFormGroup = undefined;
  }

  public showUpload(id: number): void {
    this.router.navigate(['/upload-details', id]);
  }


  public setBalance(): void{
    if ( this.showBalance ){
      this.incomeFormGroup.get('Balance').setValue(0);
    }else{
      this.incomeFormGroup.get('Balance').setValue(-1);
    }
  }

  public setOffsetBalance(): void{
    if ( this.showOffsetBalance ){
      this.incomeFormGroup.get('OffsetBalance').setValue(0);
    }else{
      this.incomeFormGroup.get('OffsetBalance').setValue(-1);
    }
  }

  public showFilter(): void{
    this.filterDialog.show();
  }

  public doFilter(filter: PayInListFilterModel): void {
    this.filter.BalanceTo = filter.BalanceTo;
    this.filter.BalanceFrom = filter.BalanceFrom;
    this.filter.AmountFrom = filter.AmountFrom;
    this.filter.AmountTo = filter.AmountTo;

    this.filter.Take = filter.Take;
    this.filter.TrailFrom = filter.TrailFrom;
    this.filter.TrailTo = filter.TrailTo;
    this.filter.IdFrom = filter.IdFrom;
    this.filter.IdTo = filter.IdTo;
    this.filter.TsFrom  = filter.TsFrom;
    this.filter.TsTo = filter.TsTo;
    this.loadFilteredData();
  }

  public pageChange(event: PageChangeEvent): void {
    this.filter.Skip = event.skip;
    this.loadFilteredData();
  }

  public sortChange(sort: SortDescriptor[]): void {
    this.filter.Sort = sort;
    this.loadFilteredData();
  }

  public onLoanChange(loan: LoanModel): void {
    if ( loan.Id !== '' ) {
      this.incomeFormGroup.get('Lender').setValue(loan.Lender);
      this.incomeFormGroup.get('Lender').disable({onlySelf: true, emitEvent: false});
    }
  }
}
