import { Component, OnInit, Input, ViewContainerRef, ViewChild, ComponentFactory, ComponentFactoryResolver, ViewChildren, QueryList, Output, EventEmitter, AfterViewInit } from '@angular/core';
import { NotificationService, StringToDatePipe, BooleanToStringPipe, LocalizedDatePipe } from '@xdf/commons';
import { Router, ActivatedRoute } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { MatSort } from '@angular/material/sort';
import { trigger, state, transition, animate, style } from '@angular/animations';
import { DatePipe, DecimalPipe } from '@angular/common';
import { SelectionModel } from '@angular/cdk/collections';
import { AuditDialogService, ColumnTemplate, ConfirmationDialogService, DataTableInnerRow, FieldFilter, GridColumn } from '@xdf/gallery';
import { CalendarExceptionDialogService } from '../../../../calendar-form/services/calendar-exception-dialog.service';
import { CalendarExceptionService } from '../../../../services/calendar-exception.service';
import { MatTable, MatTableDataSource } from '@angular/material';

const DEFAULT_LABELS = {
  deleteTitle: 'title.delete.confirmation',
  deleteDesc: 'message.delete.confirmation',
  deleteSuccess: 'message.delete.ok'
};

const CALENDAR_EXCEPTION = {
  'H': 'calendar-exception.type.h',
  'N': 'calendar-exception.type.n',
  'W': 'calendar-exception.type.w'
};
const FREQUENCY = {
  'U': 'calendar-exception.frequency.u',
  'W': 'calendar-exception.frequency.w',
  'Y': 'calendar-exception.frequency.y',
  'R': 'calendar-exception.frequency.r'
};

@Component({
  selector: 'byte-calendar-exception-table',
  templateUrl: './calendar-exception-table.component.html',
  styleUrls: ['./calendar-exception-table.component.scss'],
  animations: [
    trigger('detailExpand', [
      state('collapsed', style({ height: '0px', minHeight: '0', padding: '0' })),
      state('expanded', style({ height: '*', padding: '5px 10px' })),
      transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
    ]),
  ],
})
export class CalendarExceptionTableComponent implements OnInit, AfterViewInit {

  filterValue;
  @Input() calendarId: string;
  @Input() mode: string;
  @ViewChild(MatSort, { static: false }) sort: MatSort;
  @ViewChild('calendarTable', { static: false }) myTable: MatTable<any>;
  @ViewChildren('innerContainer', { read: ViewContainerRef })
  templates!: QueryList<any>;

  componentRef: any;

  @Input() resourceAuth = {};
  @Input() columnTemplateArray: ColumnTemplate[];
  @Input() sortColumn: string;
  @Input() sortDirection;
  @Input() showFilterBar = true;
  @Input() definitionReport;
  @Input() customLabels: {};
  @Input() calendarExceptionList;
  @Input() calendarExceptionGrid;
  innerFactory: ComponentFactory<any>;

  @Output() choosedOption: EventEmitter<any> = new EventEmitter<any>();
  @Output() dirtyChange: EventEmitter<any> = new EventEmitter<any>();
  selection = new SelectionModel<any>(true, []);

  @Input() editMultiple = false;

  dataSource: MatTableDataSource<any>;
  filterTags = [];
  displayedColumns = new Array<string>();
  additionalColumns = new Array<GridColumn>();
  fieldFilters = new Array<FieldFilter>();
  additionalOptions = [];
  expandedElement: any;

  constructor(
    protected route: ActivatedRoute,
    protected router: Router,
    private translate: TranslateService,
    protected vcRef: ViewContainerRef,
    protected confirmationDialogService: ConfirmationDialogService,
    protected notificationService: NotificationService,
    protected auditDialogService: AuditDialogService,
    private resolver: ComponentFactoryResolver,
    private stringToDate: StringToDatePipe,
    private datePipe: DatePipe,
    private decimalPipe: DecimalPipe,
    private booleanToString: BooleanToStringPipe,
    private localizedDate: LocalizedDatePipe,
    private calendarExceptionDialogService: CalendarExceptionDialogService,

    private calendarExceptionService: CalendarExceptionService,
  ) {
    const calendarExceptionDataKey = 'calendarExceptionData';
  }

  ngAfterViewInit(): void {
    if (this.sort) {
      this.sort.sortChange.subscribe(() => {
        if (!this.sort.disabled && this.sort.active) {
          this.sortDirection = this.sort.direction;
          this.sortColumn = this.sort.active;
          this.dataSource.sort = this.sort;
        }

      });
    }
  }

  ngOnInit() {
    const calendarExceptionDataKey = 'calendarExceptionData';
    this.dataSource = new MatTableDataSource(this.calendarExceptionList);
    this.calendarExceptionList.forEach(item => {
      item.calendarException = this.translate.instant(CALENDAR_EXCEPTION[item.calendarExceptionType]);
      item.frequency = this.translate.instant(FREQUENCY[item.frequencyType]);
    });
    if (this.editMultiple) {
      this.displayedColumns.push('select');
    }
    this.columnTemplateArray.forEach(column => {
      if (column.filtable) {
        this.fieldFilters.push(new FieldFilter(column.title, column.name, column.queryName, column.type, column.values));
      }

      if (!column.visible) {
        this.additionalColumns.push(new GridColumn(column.name, column.title));
      } else {
        this.displayedColumns.push(column.name);
      }
    });

    this.displayedColumns.push('actions');


    if (this.resourceAuth) {
      const keys = Object.keys(this.resourceAuth);
      keys.forEach(key => {
        switch (key) {
          case 'edit':
          case 'view':
          case 'delete':
          case 'export':
          case 'new':
            break;
          default:
            this.additionalOptions.push(key);
        }
      });
    }
  }

  onFilter(filterValue) {
    this.dataSource.filter = filterValue;
  }



  onNewRecord() {
    this.calendarExceptionDialogService.loadComponent(this.vcRef, 'calendar_exception_new', undefined, 'new').subscribe(result => {
      if (result && result['success']) {
        result['record'].calendarException = this.translate.instant(CALENDAR_EXCEPTION[result['record'].calendarExceptionType]);
        result['record'].frequency = this.translate.instant(FREQUENCY[result['record'].frequencyType]);
        this.dataSource.data.push(result['record']);
        this.refreshTable();
        this.onChangeForm();
      }
    });
  }

  onDeleteRecord(record: object, index) {
    this.confirmationDialogService.loadComponent(
      this.vcRef,
      this.getLabel('deleteTitle'),
      this.getLabel('deleteDesc')).subscribe(it => {
        if (it) {
          record['delete'] = true;
          //this.calendarExceptionGrid.push(record);
          this.dataSource.data.splice(index, 1);
          this.refreshTable();
          this.onChangeForm();
        }
      });
  }

  onRowEdited(record: object, index): void {
    this.calendarExceptionDialogService.loadComponent(this.vcRef, 'calendar_exception_edit', record, 'edit').subscribe(result => {
      if (result && result['success']) {
        result['record'].calendarException = this.translate.instant(CALENDAR_EXCEPTION[result['record'].calendarExceptionType]);
        result['record'].frequency = this.translate.instant(FREQUENCY[result['record'].frequencyType]);
        this.dataSource.data[index] = result['record'];
        //this.calendarExceptionGrid.push(result['record']);
        this.refreshTable();
        this.onChangeForm();
      }
    });
  }

  onRowClicked(record: object): void {
    this.calendarExceptionDialogService.loadComponent(this.vcRef, 'calendar_exception_view', record, 'view').subscribe(result => {
      if (result && result['success']) {
      }
    });
  }



  isOdd(index) {
    return (index % 2) === 0;
  }

  expandClick(item) {
    this.expandedElement = this.expandedElement === item ? null : item;

    this.templates.forEach((item: any) => {
      item.clear();
      this.componentRef = item.createComponent(this.innerFactory);
      if (this.componentRef.instance instanceof DataTableInnerRow) {
        this.componentRef.instance.setData(this.expandedElement);
      }
    });
  }

  getValue(item, columnTemplate: ColumnTemplate) {
    if (columnTemplate.type === 'valpos') {

      const keys = Object.keys(columnTemplate.values);

      for (const index in keys) {
        if (index) {
          const key = keys[index];
          if (key === item[columnTemplate.name]) {
            const text = this.translate.instant(columnTemplate.values[key]);
            return text;
          }
        }
      }
    } else if (columnTemplate.type === 'date') {
      let dateTimeFormat = 'mediumDate';
      if (columnTemplate.dateFormat) {
        dateTimeFormat = columnTemplate.dateFormat;
      }
      const date = this.stringToDate.transform(item[columnTemplate.name]);
      return this.localizedDate.transform(date, dateTimeFormat);
    } else if (columnTemplate.type === 'decimal') {
      let digitsInfo = '1.2-2';
      if (columnTemplate.digitsInfo) {
        digitsInfo = columnTemplate.digitsInfo;
      }
      return this.decimalPipe.transform(item[columnTemplate.name], digitsInfo);
    } else if (columnTemplate.type === 'boolean') {
      const valueText: string = this.booleanToString.transform(item[columnTemplate.name]);
      return this.translate.instant(valueText);
    } else if (columnTemplate.type === 'datetime') {
      let dateTimeFormat = 'medium';
      if (columnTemplate.dateFormat) {
        dateTimeFormat = columnTemplate.dateFormat;
      }
      return this.localizedDate.transform(item[columnTemplate.name], dateTimeFormat);
    } else {
      if (columnTemplate.aliasName) {
        return item[columnTemplate.aliasName];
      } else {
        return item[columnTemplate.name];
      }
    }
  }

  getClassText(item, columnTemplate: ColumnTemplate) {
    if (columnTemplate && columnTemplate.type === 'valpos' && columnTemplate.styles) {
      const keys = Object.keys(columnTemplate.values);

      for (const index in keys) {
        const key = keys[index];
        if (key === item[columnTemplate.name]) {
          return columnTemplate.styles[key];
        }
      }
    }
    return '';
  }

  getClassCol(item, columnTemplate: ColumnTemplate) {
    if (columnTemplate && columnTemplate.type === 'decimal') {
      return 'text-right';
    } else if (columnTemplate && columnTemplate.type === 'boolean') {
      return 'text-center';
    }
    return 'text-left';
  }

  getStyleText(colStyle, item) {
    if (colStyle && item[colStyle]) {
      const colStyleObject = JSON.parse(item[colStyle]);
      return colStyleObject;
    }
    return {};
  }

  isAllSelected() {
    const numSelected = this.selection.selected.length;
    const numRows = this.dataSource.data.length;
    return numSelected === numRows;
  }

  /** Selects all rows if they are not all selected; otherwise clear selection. */
  masterToggle() {
    this.isAllSelected() ?
      this.selection.clear() :
      this.dataSource.data.forEach(row => this.selection.select(row));
  }

  private getLabel(type: string) {
    return (this.customLabels && this.customLabels[type]) ? this.customLabels[type] : DEFAULT_LABELS[type];
  }

  private refreshTable() {
    // If there's no data in filter we do update using pagination, next page or previous page
    if (this.myTable) {
      let filterTemp = this.dataSource.filter;
      this.dataSource.filter = '';
      this.dataSource.filter = filterTemp;
      if (this.sort) {
        this.sort.sortChange.subscribe(() => {
          if (!this.sort.disabled && this.sort.active) {
            this.sortDirection = this.sort.direction;
            this.sortColumn = this.sort.active;
            this.dataSource.sort = this.sort;
          }

        });
      }
    }
  }

  deleteFilter() {
    this.filterValue = '';
    this.dataSource.filter = '';
  }

  onChangeForm() {
    this.dirtyChange.emit(true);
  }
}
