import {
  GridColumnIdUtils,
  GridRow,
  GridRowModelType,
  GridV2,
  GridV2Column,
  Visible
} from "@webbpm/base-package";
import {ChangeDetectionStrategy, Component} from "@angular/core";
import {
  ColDef,
  GridReadyEvent,
  ICellRendererParams,
  ITooltipParams,
  ValueFormatterParams,
  ValueGetterParams,
} from "ag-grid-community";
import {StaticColumnInitializer} from "./StaticColumnInitializer";
import {
  InMemoryStaticGridRpcService
} from "../../../generated/ru/micord/ervu/service/rpc/InMemoryStaticGridRpcService";
import {StaticGridColumn} from "../../../generated/ru/micord/ervu/property/grid/StaticGridColumn";
import {FilterService} from "../../service/FilterService";
import {AuditConstants, AuditService, FilterInfo} from "../../service/AuditService";
import {ValidateFileService} from "../../service/ValidateFileService";


@Component({
             moduleId: module.id,
             selector: 'in-memory-static-grid',
             templateUrl: './../../../../../src/resources/template/ervu/component/grid/GridV2.html',
             changeDetection: ChangeDetectionStrategy.OnPush
           })
export class InMemoryStaticGrid extends GridV2 {

  private rpcService: InMemoryStaticGridRpcService;
  private auditService: AuditService;
  private validateFileService: ValidateFileService;

  getRowModelType(): string {
    return GridRowModelType.CLIENT_SIDE;
  }

  protected initGrid() {
    super.initGrid();
    this.auditService = this.injector.get(AuditService);
    this.validateFileService = this.injector.get(ValidateFileService);
    this.rpcService = this.getScript(InMemoryStaticGridRpcService);
    if (this.rpcService) {
      this.rpcService.loadData().then(response => {
        this.rowData = response;
        this.refresh();
      })
          .catch((error) => console.error(`Failed to load data. ${error}`));
    }
  }

  onGridReady(event: GridReadyEvent) {
    super.onGridReady(event);
    this.addColumnFilterChangeListener(() => {
      this.auditActiveFilters();
    })
  }

  private auditActiveFilters() {
    const filterModel = this.gridApi.getFilterModel();
    if (!filterModel || Object.keys(filterModel).length === 0) {
      return;
    }

    const filterMap: Record<string, FilterInfo> = {};
    Object.entries(filterModel).forEach(([column, agFilter]) => {
      const columnDef = this.gridApi.getColumnDef(column);
      if (!columnDef) {
        return;
      }

      const data = FilterService.getFilterData(columnDef, agFilter);
      if (!data) {
        return;
      }

      filterMap[columnDef.headerName] = data;
    });

    if (Object.keys(filterMap).length > 0) {
      this.auditService.logActionAudit(AuditConstants.FILTER_EVENT, filterMap);
    }
  }

  public downloadFile(fileId : string){
    this.validateFileService.exportFile(fileId);
  }

  getColumns(): any[] {
    return this.getScriptsInChildren(GridV2Column)
        .map(columnV2 => columnV2.getScript(StaticGridColumn));
  }

  protected columnV2ToColumnDef(column: GridV2Column): ColDef {
    let gridColumn = column.getScript(StaticGridColumn);
    let colDef = this.columnToColumnDef(gridColumn);
    if (column.renderer) {
      colDef.cellRenderer = (params: ICellRendererParams) => column.renderer.render(params);
    }
    if (column.valueGetter) {
      colDef.valueGetter = (params: ValueGetterParams) => column.valueGetter.get(params);
    }
    if (column.tooltipValueGetter) {
      if (gridColumn.columnTooltip) {
        throw new Error(
            "Only one type of tooltip should be specified: tooltipValueGetter or columnTooltip");
      }
      colDef.tooltipValueGetter = (params: ITooltipParams) => column.tooltipValueGetter.get(params);
    }
    column.setGridRef(this);
    column.setColDef(colDef);
    return colDef;
  }

  protected columnToColumnDef(column: any): ColDef {
    let colDef = StaticColumnInitializer.columnToColumnDef(this, column);
    let columnComp = column.context;
    colDef['columnUid'] = columnComp.getObjectId();

    if (columnComp.cellCssClassRulesProvider) {
      colDef.cellClassRules = columnComp.cellCssClassRulesProvider.getRules();
    }

    if (columnComp.valueFormatter) {
      colDef.valueFormatter = (params?: ValueFormatterParams) => {
        return columnComp.valueFormatter.format(params);
      }
    }

    colDef.cellRendererParams = {
      context : {
        parentComponent: this
      }
    };

    return colDef;
  }

  public load(): void {
    this.onLoadStart();
    let rows: GridRow[] = [];

    if (this.rowData) {
      this.rowData.forEach((data, i) => {
        let row: GridRow = new GridRow();
        row[GridColumnIdUtils.ROW_UID] = i;
        this.getColumns().forEach(col => {
          let column = col.field.column;
          row[column] = data[column];
        })
        rows.push(row);
      })
    }
    this.getGridApi().setRowData(rows);
    this.onLoadEnd();
  }

  @Visible()
  public getRowDataSize(): number {
    return this.rowData ? this.rowData.length : 0;
  }
}
