import { ReactNode } from 'react'
import { Table as RawTable } from 'antd'
import { tryAddKeys } from './EditableTable'
import { makeNumericSorter, makeStringSorter} from './sorters'
export { makeDateSorter, makeNumericSorter, makeStringSorter} from './sorters'
export { EditableTable } from './EditableTable'
export { DatePickerWrapper } from './DatePickerWrapper'
export { SelectFromDictionary } from './SelectFromDictionary'

export const RegExpIsFloat = /^[-+]?\d+\.?\d*$/
export const formatDate='YYYY.MM.DD HH:mm'

export const makeNumericRender = (fixed?:number) => (value: any, row: object): ReactNode => {
  const placeholder = '-'
  let val = placeholder
  if((value !== null) || 
    (value !== undefined) || 
    Number.isNaN(value) ||
    !Number.isFinite(value)){
      val = !!fixed 
      ? (+value).toFixed(fixed) 
      : (+value).toPrecision(5)
    }
  
  return (<div className='text-align-r-container'>
    <span>{val}</span>
  </div>)
}

export const makeNumericColumnOptions = (fixed?:number, sorterKey?:string ) => ({
  editable: true,
  initialValue: 0,
  width:100,
  sorter: sorterKey? makeNumericSorter(sorterKey) : null,
  formItemRules: [
    {
      required: true,
      message: `Введите число`,
      pattern: RegExpIsFloat,
    },
  ],
  render: makeNumericRender(fixed),
})

/*
other - объект с дополнительными свойствами колонки
поддерживаются все базовые свойства из описания https://ant.design/components/table/#Column
плю дополнительные для колонок EditableTable: */
interface columnPropsOther {
  // редактируемая колонка
  editable?: boolean
  // react компонента редактора
  input?: ReactNode
  // значение может быть пустым
  isRequired?: boolean
  // css класс для <FormItem/>, если требуется
  formItemClass?: string
  // массив правил валидации значений https://ant.design/components/form/#Rule
  formItemRules?: any[]
  // дефолтное значение при добавлении новой строки
  initialValue?: string|number
}

export const makeColumn = (title:string | ReactNode, key:string, other?:columnPropsOther) => ({
  title: title,
  key: key,
  dataIndex: key,
  ...other,
})

export const makeColumnsPlanFact = (title:string | ReactNode, key:string|string[], columsOther?:any|any[], gruopOther?:any) =>
{
  let keyPlanLocal = key
  let keyFactLocal = key
  
  if(key instanceof Array){    
    keyPlanLocal = key[0]
    keyFactLocal =  key[1]
  }else{
    keyPlanLocal = key + 'Plan'
    keyFactLocal =  key + 'Fact'
  }

  let columsOtherLoacl :any[2]
  if(columsOther instanceof Array)
    columsOtherLoacl = [columsOther[0], columsOther[1]]
  else
    columsOtherLoacl = [columsOther, columsOther]

  return {  
    title: title,
    ...gruopOther,
    children: [
      makeColumn('план', keyPlanLocal, columsOtherLoacl[0]),
      makeColumn('факт', keyFactLocal, columsOtherLoacl[1]),
    ]
  }
}

export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) =>
  dataItem[key] === filterValue

export const makeGroupColumn = (title: string, children: object[]) => ({  
  title: title,
  children: children,
})

export const makeTextColumn = (
  title: string, 
  dataIndex: string, 
  filters: object[], 
  sorter?: (key: string) => any, 
  render?: any, 
  other?: any) => ({  
    title: title,
    dataIndex: dataIndex,
    key: dataIndex,
    filters: filters,
    onFilter: filters ? makeFilterTextMatch(dataIndex) : null,
    sorter: sorter ?? makeStringSorter(dataIndex),
    render: render,
    ...other
})

export const makeNumericColumn = (title: string, dataIndex: string, 
  filters: object[], filterDelegate: (key: string | number) => any,
  renderDelegate: (_: any, row: object) => any, width: string, other?: columnPropsOther) => ({  
    title: title,
    dataIndex: dataIndex,
    key: dataIndex,
    filters: filters,
    onFilter: filterDelegate ? filterDelegate(dataIndex) : null,
    sorter: makeNumericSorter(dataIndex),
    width: width,
    render: renderDelegate??makeNumericRender(),
    align: 'right',
    ...other
})

export const makeNumericColumnPlanFact = (title: string, dataIndex: string, filters: object[], 
    filterDelegate: (key: string | number) => any, renderDelegate: (_: any, row: object) => any, width: string) => 
  makeGroupColumn( title, [
    makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, renderDelegate, width),
    makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, renderDelegate, width),
  ])

export const makeNumericStartEnd = (
  title: string,
  dataIndex: string,
  fixed: number,
  filters: object[],
  filterDelegate: (key: string | number) => any,
  renderDelegate: (_: any, row: object) => any,
  width: string,
) => makeGroupColumn( title, [
    makeNumericColumn('старт', dataIndex + 'Start', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Start')),
    makeNumericColumn('конец', dataIndex + 'End', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'End'))
])

export const makeNumericAvgRange = (
    title: string,
    dataIndex: string,
    fixed: number,
    filters: object[],
    filterDelegate: (key: string | number) => any,
    renderDelegate: (_: any, row: object) => any,
    width: string
) => makeGroupColumn( title, [
    makeNumericColumn('мин', dataIndex + 'Min', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Min')),
    makeNumericColumn('сред', dataIndex + 'Avg', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Avg')),
    makeNumericColumn('макс', dataIndex + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Max'))
])

type PaginationContainer = {
  skip?: number;
  take?: number;
  count?: number;
  items?: any[] | null;
}

export const makePaginationObject = (paginationContainer:PaginationContainer, ...other:any) => {
  let page = 1 + Math.floor((paginationContainer.skip??0) /(paginationContainer.take??1));
  return {
    ...other,
    pageSize: paginationContainer.take,
    total: paginationContainer.count ?? paginationContainer.items?.length ?? 0,
    current: page,
  }
}

interface TableContainer {
  dataSource: any[];
  children?: any;
}

export const Table = ({dataSource, children, ...other}: TableContainer) => {
  return <RawTable dataSource={tryAddKeys(dataSource)} {...other}>{children}</RawTable>
}
