import { DataUnit, Filter } from '@sankhyalabs/core';
import { Components } from '../../../components';
import { IInvalidField, IRecordValidator } from '../../../utils/form/interfaces';
import { ICustomEditorInfo } from '../../../utils/customEditor/interfaces/ICustomEditorInfo';
import { ICustomRenderInfo } from '../../../utils/customRender/interfaces/ICustomRenderInfo';
import { ICustomFormatter } from '../interfaces';
import FilterCollumn = Components.FilterColumn;
import { TFunction } from 'i18next';
/**
 * O intuito desta abstração, é isolar o componente EzGrid de uma implementação
 * específica, permitindo que usemos componentes de terceiros sem um acoplamento
 * direto.
 * Isso permitirá que no futuro possamos trocar a implementação usada sem prejuízo
 * às aplicações que o usam.
 *
 * IMPORTANTE: Como consumidores de API de terceiros precisamos manter toda e qualquer
 * funcionalidade abstrata, ou seja, se o componente usa determinada funcionalidade da
 * implementação de referência essa funcionalidade deve estar COMPLETAMENTE abstraída
 * pelo controller, sob pena de inviabilizar a troca da implementação usada.
 */
export default interface EzGridController {
  /**
   * Chamado pelo EzGrid para criar os elementos DOM da grade.
   * @param container - O elemento que será usado como host para construir a grade.
   * @param options - A contextualização dessa instância de grade.
  */
  initDatagrid(container: HTMLElement, options: EzGridOptions): void;
  /**
   * Método responsável por receber a definição das colunas.
   * @param cols - Array contendo a definição de todas as colunas.
   * para controlar a seleção.
   */
  setColumnsDef(cols: Array<EzGridColumn>): void;
  /**
  * Retorna a definição das colunas.
  * @return - Array contendo as definições de cada coluna.
  */
  getColumnsDef(): Array<EzGridColumn>;
  /**
   * Recebe o estado das colunas. Geralmente o estado pode ser persistido separadamete
   * da definição básica da coluna. Nesse caso esse método o recebe e aplica.
   * @param state - Array contendo as informações de estado de cada coluna.
   */
  setColumnsState(state: Array<EzGridColumnConfig>): void;
  /**
   * Retorna o estado das colunas.
   * @return - Array contendo as informações de estado de cada coluna.
   */
  getColumnsState(): Array<EzGridColumn>;
  /**
   * Seleção de linhas.
   * @returns Retorna um array com a(s) linha(s) selecionada(s).
   */
  getSelection(): Array<any>;
  /**
   * Adiciona um item de menu a ser colocado no cabeçalho das colunas.
   * @param item - A definição do item que deve ser inserido no menu.
   */
  addColumnMenuItem(item: EzGridColumnMenuItemDef): void;
  /**
   * Método responsável por atribuir o array de linhas da grade.
   * @param data - Array contendo objetos json que representam
   * as linhas da grade (os dados propriamente ditos).
   */
  setData(data: Array<any>): void;
  /**
   * Método responsável por adicionar linhas novas
   */
  addRows(rows?: Array<any>): void;
  /**
   * Método responsável por atualzar linhas da grid
   */
  updateRows(rows?: Array<any>): void;
  /**
  * Método responsável por remover linhas da grade
  */
  removeRows(rows?: Array<any>): void;
  /**
   * Método responsável por selecionar linhas
   */
  selectRows(rowIds: Array<string>, quietly?: boolean): void;
  /**
   * Método responsável por selecionar todas as de uma vez.
   */
  selectAll(quietly?: boolean): void;
  /**
  * Método responsável por alterar o valores nos registros
  */
  changeValues(changes: any, rowIds?: Array<string>): void;
  /**
   * Método responsável por atualizar as linhas da grade
   */
  refresh(scrollToSelectedRow?: boolean): void;
  /**
   * Método responsável limpar celulas invalidas
   */
  clearInvalidCells(stopEdition?: boolean): void;
  /**
   * Metodo responsável por lidar com o cancelamento da edição na grade
   */
  processEditionCanceled(): void;
  /**
   * Método responsável por lidar com edição contínua
   */
  processContinuousInsert(): void;
  /**
   * Método responsável por atualizar as linhas selecionadas da grade
   */
  refreshSelectedRows(): void;
  /**
   * Adiciona um filtro rápido na grid e faz o refresh.
   */
  quickFilter(term: string): void;
  /**
   * Foca a ultima linha da grade, usado durante a troca de página
   */
  setFocusLastRow(): void;
  /**
   * Foca a primeira linha da grade, usado durante a troca de página
   */
  setFocusFirstRow(): void;
  /**
   * Foca em uma linha específica, garante que ela está visível e inicia edição.
   */
  startEditionOnRowByIndex(index: number): void;
  /**
   * Foca na última linha, garante que ela está visível e inicia edição.
   */
  startEditionOnLastRow(): void;
  /**
   *  Define se a grade será focada automaticamente.
   */
  setAutoFocus(autoFocus: boolean): void;
  /**
   * Ativa inserção de registros no modo grade.
   */
  setEnableGridInsert(enable: boolean): void;
  /**
   * Ativa/desativa a inserção continua na grade
   * Só funciona quando a prop enableGridInsert está ativa
  */
  setEnableContinuousInsert(enable: boolean): void;
  /**
   * Método responsável por retornar a configuração da grade.
   */
  getGridConfig(): Array<EzGridColumnConfig>;
  /**
   * Localiza determinada coluna tornando-a visível.
   */
  locateColumn(columnName: string, gridElement: HTMLElement): void;
  configFilterColumn(filterColumn: FilterCollumn): any;
  getFilter(): Array<Filter> | undefined;
  clearFilter(): void;
  /**
   * Registra editores customizados no controller da grid.
   */
  setCellEditors(customEditors: Map<string, ICustomEditorInfo>): void;
  /**
   * Registra renders customizados no controller da grid.
   */
  setCellRenders(customRenders: Map<string, ICustomRenderInfo>): void;
  clearFilter(): void;
  setCustomFormatters(customFormatters: Map<string, ICustomFormatter>): void;
  setFocus(): void;
  savingCanceled(fields: Array<IInvalidField>, recordId: string): void;
  destroy(): void;
  registryListeners(): void;
  resetPaginationState(): void;
  stopEdit(): void;
  /**
   Remove coluna de seleção por checkbox
  */
  hideSelectionColumn(): void;
  /**
   Mostra coluna de seleção por checkbox
  */
  showSelectionColumn(): void;
  /**
   * Limpa a seleção das células da grade
   */
  clearRangeSelection(): void;
}
/**
 * Carrega as informações necessárias para contextualizar corretamente a instância.
 */
export interface EzGridOptions {
  /**
   * Callback a ser chamado quando algum atributo das colunas é alterado.
   */
  onColumnStateChange: Function;
  /**
   * Callback a ser chamado quando as linhas selecionadas mudam.
   */
  onSelectionChange: Function;
  /**
  * Callback para reagir à troca de páginas
  */
  onPaginationChange: Function;
  /**
  * Callback para reagir à atualização da paginação vinda do Parallel Loader
  */
  onPaginationUpdate: Function;
  /**
  * Callback para reagir ao clique duplo na linha
  */
  onDoubleClick: Function;
  /**
  * Callback para reagir ao refresh do controller
  */
  onRefresh: Function;
  /**
   * Usado para permitir múltipla seleção.
   */
  allowMultipleSelection: boolean;
  /**
   * Endereço do servidor para buscar os dados.
   */
  serverURL: string;
  /**
   * Repositório de dados, controla a manipulação dos dados.
   */
  dataUnit: DataUnit;
  /**
   * Configuração do valor da coluna de status.
   * Exemplo: { "RECDESP": { "-1" : "#BD0025", "1" : "#157A00" } }
   */
  statusResolver: IStatusResolver | StatusResolverFunction;
  /**
   * Quando verdadeiro, o ENTER fará a navegação como se fosse a tecla TAB na grade.
   */
  useEnterLikeTab: boolean;
  /**
   * Antes de executar o salvamento da edição, pode-se atribuir um validador de registros.
   */
  recordsValidator?: IRecordValidator;
  /**
   * Desabilita edição na grade independente da configuração de coluna.
   */
  editionIsDisabled?: () => boolean;
  /**
   * Registra editores customizados no controller da grid
   */
  customEditors?: Map<string, ICustomEditorInfo>;
  /**
   * Registra renders customizados no controller da grid
   */
  customRenders?: Map<string, ICustomRenderInfo>;
  /**
   * Mapa de formatadores customizados por coluna.
   */
  customFormatters: Map<string, ICustomFormatter>;
  /**
   * Define se a grid será focada ao ser carregada.
   */
  autoFocus: boolean;
  /**
   * Ativa inserção de registros no modo grade.
   */
  enableGridInsert?: boolean;
  /**
   * Ativa/desativa a inserção continua na grade
   * Só funciona quando a prop enableGridInsert está ativa
  */
  enableContinuousInsert?: boolean;
  /**
   * Ativa o gerenciamento de locks na grade pela Taskbar.
   */
  enableLockManagerTaskbarClick?: boolean;
  /**
   * Define se o componente deve usar o LockManager para controle de carregamento da aplicação
   */
  enableLockManagerLoadingComp?: boolean;
  /**
   * Ativa/desativa modo de linhas com cores alternadas.
  */
  enableRowTableStriped?: boolean;
  /**
   * Informa se a coluna de chechbox deve ser suprimida
   */
  suppressCheckBoxCol?: boolean;
  /**
   * Define se a grade deve suprimir o scroll horizontal.
   */
  suppressHorizontalScroll?: boolean;
  /**
   * Define a função de intercionalização.
   */
  i18n: TFunction;
  /**
   * Define se a grade deve suprimir o filtro de coluna.
   */
  suppressFilterColumn?: boolean;
}
/**
 * Representa cada coluna da grade.
 */
export interface EzGridColumn {
  /**
   * Texto a ser apresentado como título da coluna.
   */
  label: string;
  /**
   * ID da coluna. Em cada linha do array de dados, esse ID deve coincidir com
   * o nome do atributo que a coluna representa.
   */
  name: string;
  /**
   * [Opcional] Representa a ordenação da coluna. Pode variar entre ASC e DESC
   */
  sort?: string;
  /**
   * [Opcional] Número inteiro positivo que representa a sequência de ordenação.
   * Importante quando há ordenação por mais de uma coluna.
   */
  sortIndex?: number;
  /**
   * [Opcional] Largura da coluna em pixels absolutos.
   */
  width?: number;
  /**
   * [Opcional] Indica que a coluna está fixada.
   */
  pinned?: boolean;
  /**
   * [Opcional] Indica que a coluna não está visível.
   */
  hidden?: boolean;
  /**
   * [Opcional] Indica o tipo de dado renderizado na coluna.
   */
  userInterface?: string;
  /**
   * [Opcional] Utilizado no caso do campo do tipo combo-box.
   */
  options?: any;
  /**
   * [Opcional] Posição em que a coluna deve ser fixada.
   */
  pinnedPosition?: string;
  /**
   * [Opcional] Define propriedades especiais da coluna
   */
  props?: Map<string, any>;
}
/**
 * Interface utilizada para se inserir menus personalizados no cabeçalho das colunas.
 */
export interface EzGridColumnMenuItemDef {
  /**
   * Texto a ser apresentado como título do item de menu.
   */
  label: string;
  /**
   * Identificador do item de menu. Esse valor será disponibilizado junto com o ID da
   * coluna ao disparar a ação respectiva.
   */
  name: string;
  /**
   * Ação executada quando o usuário aciona o menu.
   */
  action: Function;
  /**
   * Ícone que deve ser exibido ao junto ao ítem de menu.
   */
  icon?: HTMLElement | string;
}
/**
 * Evento de alteração de estado. Sempre que o estado das colunas for alterado, esse evento é disparado.
 */
export interface EzGridColumStateEvent {
  /**
   * Tipo de alteração de estado ["sort", "columnResize", "columnPinned", "columnMoved", "visibleChange"].
   */
  type: string;
  /**
   * O estado de todas as colunas depois da alteração. Usado para persistir o novo estado.
   */
  state: Array<EzGridColumn>;
  /**
  * Define se alteração foi realizada pelo usuário.
  */
  isUserChange: boolean;
}
export interface IGridConfig {
  /**
   * Lista de colunas a ser apresentada.
   */
  columns: Array<EzGridColumnConfig>;
}
export interface EzGridColumnConfig {
  /**
   * ID da coluna. Em cada linha do array de dados, esse ID deve coincidir com
   * o nome do atributo que a coluna representa.
   */
  name: string;
  /**
   * Largura padrão da coluna em pixels absolutos.
   */
  width: number;
  /**
   * Número inteiro positivo que representa a sequência de ordenação.
   * Importante quando há ordenação por mais de uma coluna.
   */
  orderIndex: number;
  /**
   * [Opcional] Define se a ordenação da coluna é ascendente ou descendente.
   */
  ascending?: boolean;
  /**
   * Largura customizada da coluna em pixels absolutos.
   */
  customWidth?: number;
  /**
   * Versão da configuração (utilizada para compatibilidade durante a leitura da config).
   */
  configVersion?: number;
}
export interface IStatusResolver {
  [fieldName: string]: Map<String, any>;
}
export type StatusResolverFunction = (data: object) => string;
