import { GridExportButtonWidth } from '../../consts';
import { ColumnConfig, EN_Alignment, EN_SortOrder, Type_FractionDigits } from './columnconfig';


export interface SortInfo {
  caption: string;
  sortIndex: number;
  sortOrder: EN_SortOrder;
}


export class ColumnConfigList {
  public overHeaders: ColumnConfig[] = [];
  private _columns: ColumnConfig[] = [];
  public get columns(): ColumnConfig[] {
    return this._columns;
  }
  public set columns(value: ColumnConfig[]) {
    this._columns = value;
    this.exportWasAdded = false;
  }

  public withExport: boolean = true;
  public curOverHeader: ColumnConfig;
  private exportWasAdded: boolean = false;

  constructor() {
  }

  clear() {
    this.overHeaders = [];
    this.columns = [];
  }

  add(caption: string = '', dataField?: string, widthFactor: number = 1): ColumnConfig {
    const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor);
    return this.addColumn(column, dataField === undefined);
  }

  addCurrency(caption: string = '', dataField?: string, widthFactor: number = 1, fractionDigits: Type_FractionDigits = 0): ColumnConfig {
    const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor, fractionDigits);
    column.cellTemplate = 'currencyTemnplate_' + fractionDigits;

    return this.addColumn(column, dataField === undefined);
  }

  addNumber(caption: string = '', dataField?: string, widthFactor: number = 1, fractionDigits: Type_FractionDigits = 0): ColumnConfig {
    if (dataField && dataField.slice(-2) === 'Id') fractionDigits = -1;
    const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor, fractionDigits);
    column.dataType = 'number';
    return this.addColumn(column, dataField === undefined);
  }

  addId(caption: string = '', dataField?: string, widthFactor: number = 1, fractionDigits: Type_FractionDigits = -1): ColumnConfig {
    const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor, fractionDigits);
    column.dataType = 'number';
    return this.addColumn(column, dataField === undefined);
  }

  addBoolean(caption: string = '', dataField?: string, widthFactor: number = 1): ColumnConfig {
    const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor);
    column.dataType = 'boolean';
    return this.addColumn(column, dataField === undefined);
  }

  addDate(caption: string = '', dataField?: string, widthFactor: number = 1): ColumnConfig {
    const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor);
    column.dataType = 'date';
    column.alignment = EN_Alignment.center;
    return this.addColumn(column, dataField === undefined);
  }

  addDateTime(caption: string = '', dataField?: string, widthFactor: number = 1): ColumnConfig {
    const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor);
    column.dataType = 'datetime';
    column.alignment = EN_Alignment.center;
    return this.addColumn(column, dataField === undefined);
  }

  private addColumn(column: ColumnConfig, overheader: boolean = false): ColumnConfig {
    const arColums: ColumnConfig[] = overheader ? this.overHeaders : this.columns;
    if (overheader) {
      column.alignment = EN_Alignment.center;
      this.curOverHeader = column;
    } else {
      if (this.curOverHeader) this.curOverHeader.subColumns.push(column);
    }
    arColums.push(column);
    return column;
  }

  //autorecalc after each add
  recalcWidth(addAdditionalColumnForExport: boolean = true) { //Calculate the weighted width  based on the widthFactor.
    if (this.withExport && this.columns[this.columns.length - 1].alignment === EN_Alignment.right && !this.exportWasAdded && addAdditionalColumnForExport) {
      this.add('', '', -GridExportButtonWidth); //last column for export
    }
    this.exportWasAdded = true;

    const totalWidthFactor: number = this.columns.reduce((sum, col) => sum + (col.visible && col.widthFactor > 0 ? col.widthFactor : 0), 0);
    if (totalWidthFactor === 0) return;
    const widthFactor_1percent: number = 100 / totalWidthFactor; //The total value may be max 100%; buffer - 0.01

    let countPosWidth = 0;
    this.columns.forEach(col => {
      if (col.visible && col.widthFactor > 0) {
        col.widthFactor = this.roundToTwo(col.widthFactor * widthFactor_1percent);
        countPosWidth++;
      }
    });
    const delta = (100 - this.columns.reduce((sum, col) => sum + (col.visible && col.widthFactor > 0 ? col.widthFactor : 0), 0));

    for (let i = this.columns.length - 1; i >= 0; i--) {
      if (this.columns[i].visible && this.columns[i].widthFactor > 0) {
        this.columns[i].widthFactor += delta;
        break;
      }
    }
  }

  roundToTwo(num: number, places = 2): number {
    return Math.round((num + Number.EPSILON) * Math.pow(10, places)) / Math.pow(10, places);
  }

  public setSorting(sortInfos: SortInfo[]) {
    for (let inx = 0; inx < this.columns.length; inx++) {
      const col = Object.assign(new ColumnConfig(), this.columns[inx]);
      const sortInfo = sortInfos.find(el => el.caption === col.caption);
      if (sortInfo) {
        col.sortIndex = sortInfo.sortIndex;
        col.sortOrder = sortInfo.sortOrder;
      } else {
        col.sortIndex = undefined;
        col.sortOrder = undefined;
      }
      this.columns[inx] = col;
    }
  }
}
