import { I18N } from 'aurelia-i18n';
import { ColDef } from 'ag-grid-community';
import moment from "moment";

import { UIInternal } from './../../../utils/ui-internal';
import { CamelCase } from './../../../utils/came-case';

import Select2CellEditor from './editors/select2-cell-editor';
import NumberCellEditor from './editors/number-cell-editor';

import { CurrencyCellRenderer } from './renderers/currency-cell-renderer';
import EnumerationRenderer from '../../renderers/enumeration-renderer';
import HyperlinkRenderer from '../../renderers/hyperlink-renderer';
import ButtonRenderer from '../../renderers/button-renderer';
import SelectionCellRenderer from '../../renderers/selection-cell-renderer';
import { ManyToManyTagRenderer } from '../../renderers/many-to-many-tag-renderer';
import TagRenderer from '../../renderers/tag-renderer';

import {
  StringFilter, BooleanFilter, BooleanFloatingFilter, NumberFilter, NumberFloatingFilter, DateFilter, DateFloatingFilter, EnumerationFilter,
  EnumerationFloatingFilter, EnumFilter, EnumFloatingFilter, StringFloatingFilter, UserFilter, UserFloatingFilter, ManyToManyFilter, ManyToManyFloatingFilter,
  OneToManyFilter, OneToManyFloatingFilter
} from '../../filters/index';
import CustomHtmlRendererEditor from './custom-html-renderer-editor';


export class CustomAgGridOptions {

  /**
   * Default AgGrid components like filters and renderers.
   *
   * @static
   * @memberof AgGridOptions
   */
  public static readonly Components = {
    'customBooleanFloatingFilter': BooleanFloatingFilter,
    'customBooleanFilter': BooleanFilter,
    'customNumberFloatingFilter': NumberFloatingFilter,
    'customNumberFilter': NumberFilter,
    'customDateFloatingFilter': DateFloatingFilter,
    'customDateFilter': DateFilter,
    'customEnumerationFloatingFilter': EnumerationFloatingFilter,
    'customEnumerationFilter': EnumerationFilter,
    'customEnumFloatingFilter': EnumFloatingFilter,
    'customEnumFilter': EnumFilter,
    'customStringFloatingFilter': StringFloatingFilter,
    'customStringFilter': StringFilter,
    'customUserFloatingFilter': UserFloatingFilter,
    'customUserFilter': UserFilter,
    'customManyToManyFloatingFilter': ManyToManyFloatingFilter,
    'customManyToManyFilter': ManyToManyFilter,
    'customOneToManyFloatingFilter': OneToManyFloatingFilter,
    'customOneToManyFilter': OneToManyFilter,
    'select2CellEditor': Select2CellEditor,
    'currencyCellRenderer': CurrencyCellRenderer,
    'enumerationRenderer': EnumerationRenderer,
    'numberCellEditor': NumberCellEditor,
    'hyperlinkRenderer': HyperlinkRenderer,
    'buttonRenderer': ButtonRenderer,
    'manyToManyTagRenderer': ManyToManyTagRenderer,
    'selectionCellRenderer': SelectionCellRenderer,
    'customHtmlRendererEditor': CustomHtmlRendererEditor,
    'tagRenderer': TagRenderer
  }

  /**
   * Get the defaults columns types definitions.
   *
   * @static
   * @param {I18N} i18n
   * @param {string} numberFloatingFilterDefaultLocale: the default locale for the number's display.
   * @return {*}  {{ [key: string]: ColDef<any>; }}
   * @memberof AgGridOptions
   */
  public static ColumnTypeDefinitions(i18n: I18N, numberFloatingFilterDefaultLocale: string): { [key: string]: ColDef<any>; } {
    return {
      "Base": {
        sortable: true,
        resizable: true
      },
      "String": {
        sortable: true,
        resizable: true,
        filter: 'customStringFilter',
        floatingFilterComponent: 'customStringFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        },

      },
      "Html": {
        sortable: true,
        resizable: true,
        filter: 'customStringFilter',
        floatingFilterComponent: 'customStringFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        },
        cellRenderer: (data) => {
          if (data.value != null) {
            return data.value;
          }
          return;
        }
      },
      "Number": {
        sortable: true,
        resizable: true,
        filter: 'customNumberFilter',
        floatingFilterComponent: 'customNumberFloatingFilter',

        floatingFilterComponentParams: {
          suppressFilterButton: true,
          defaultLocale: numberFloatingFilterDefaultLocale
        },
        cellStyle: { "text-align": "right" },
        valueFormatter: (params) => {
          if (params.data?.[params.colDef.field] != null) {
            return (!isNaN(params.data[params.colDef.field])
              ? new Intl.NumberFormat(numberFloatingFilterDefaultLocale, { minimumFractionDigits: params.colDef.cellRendererParams.minimumFractionDigits, maximumFractionDigits: params.colDef.cellRendererParams.maximumFractionDigits }).format(params.data[params.colDef.field])
              : params.data[params.colDef.field]);
          }
          return;
        },
        cellRendererParams: {
          minimumFractionDigits: 0,
          maximumFractionDigits: 2
        }
      },
      "Currency": {
        sortable: true,
        resizable: true,
        filter: 'customNumberFilter',
        floatingFilterComponent: 'customNumberFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        },
        cellStyle: { "text-align": "right" },
        cellRenderer: 'currencyCellRenderer'
      },
      "Date": {
        sortable: true,
        resizable: true,
        filter: 'customDateFilter',
        floatingFilterComponent: 'customDateFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true,
          dateFormat: "DD/MM/YYYY"
        },
        valueFormatter: (data) => {
          if (data.value != null) {
            if (data.colDef.floatingFilterComponentParams?.dateFormat != null) {
              return moment(data.value).format(data.colDef.floatingFilterComponentParams.dateFormat);
            }
          }
          return '';
        }
      },
      "DateTime": {
        sortable: true,
        resizable: true,
        filter: 'customDateFilter',
        floatingFilterComponent: 'customDateFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true,
          dateFormat: "DD/MM/YYYY HH:mm:ss"
        },
        valueFormatter: (data) => {
          if (data.value != null) {
            if (data.colDef.floatingFilterComponentParams?.dateFormat != null) {
              return moment(data.value).format(data.colDef.floatingFilterComponentParams.dateFormat);
            }
          }
          return '';
        }
      },
      "Boolean": {
        sortable: true,
        resizable: true,
        filter: 'customBooleanFilter',
        floatingFilterComponent: 'customBooleanFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        },
        valueGetter: (data) => {
          if (data.data != null) {
            let temp = UIInternal.getValue(data.data, data.colDef.field);
            return (temp === true ? i18n.tr("general.yes", { ns: "common" }) : i18n.tr("general.no", { ns: "common" }));
          }
          return;
        }
      },
      "Enumeration": {
        sortable: true,
        resizable: true,
        floatingFilter: false,
        filter: 'customEnumerationFilter',
        floatingFilterComponent: 'customEnumerationFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        },
        cellRenderer: 'enumerationRenderer'
      },
      "Enum": {
        sortable: true,
        resizable: true,
        filter: 'customEnumFilter',
        floatingFilterComponent: 'customEnumFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        },
        valueGetter: (data) => {
          if (data.data != null) {
            let temp = UIInternal.getValue(data.data, data.colDef.field);
            if (data.data?.[data.colDef.field] != null && data.colDef.floatingFilterComponentParams?.category != null) {
              return i18n.tr(data.colDef.floatingFilterComponentParams.category + "." + CamelCase.toCamelCase(temp as string));
            }
          }
          return;
        }
      },
      "User": {
        sortable: true,
        resizable: true,
        filter: 'customUserFilter',
        floatingFilterComponent: 'customUserFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        }
      },
      "ManyToMany": {
        sortable: false,
        resizable: true,
        filter: 'customManyToManyFilter',
        floatingFilterComponent: 'customManyToManyFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        },
        valueGetter: (data) => {
          if (data.data != null) {
            let allFieldPath: Array<string> = data.colDef.field.split('.');
            let arrayField = data.colDef.floatingFilterComponentParams.arrayField ?? data.colDef.field.split('.')[0];
            let arrayIndex = allFieldPath.findIndex(x => x == arrayField);
            let fieldPath: Array<string> = allFieldPath.slice(arrayIndex + 1);
            let arrayName: Array<string> = allFieldPath.slice(0, arrayIndex + 1);
            let array: any = data.data;
            arrayName.forEach(x => {
              if (array != null) {
                array = array[x];
              }
            });
            if (array == null) {
              return "";
            }
            return (array as Array<any>).map((element: any) => {
              let fieldValue = element;
              for (let fieldName in fieldPath) {
                if (fieldValue == null) return '';
                fieldValue = fieldValue[fieldName];
              }
              return fieldValue as string;
            }).join(", ");
          }
        }
      },
      "OneToMany": {
        sortable: true,
        resizable: true,
        filter: 'customOneToManyFilter',
        floatingFilterComponent: 'customOneToManyFloatingFilter',
        floatingFilterComponentParams: {
          suppressFilterButton: true
        }
      }
    }

  }

}