import React, { memo } from 'react';
import { calcOffsets, mapFixedClass, getPageInfo } from '../helpers';
import { HeaderRow, SortIcon, TD, Dropdown, InlineFlex } from '../style';
import Checkbox from '../../checkbox';
import { IColumn, ITable } from '../types';
type IProps = {
    tableProps: ITable;
    columns: IColumn[];
    state: any;
    dispatch: any;
    rowData: any[];
};
const getFilterState = (state: any, changedKey: string, changedValue: any) => {
    const filters: object[] = [{ key: changedKey, value: changedValue }];
    Object.entries(state).forEach(([stateKey, value]) => {
        const colKey = stateKey.replace('Filter', '');
        if (stateKey.endsWith('Filter') && value && colKey !== changedKey) {
            filters.push({ key: colKey, value });
        }
    });
    return filters;
};

const renderTitle = (col: IColumn, state: any, dispatch: any, onChange: any) => {
    if (col.filter) {
        if (col.sorter) {
            throw new Error('过滤和排序只能定义其一');
        }
        const key = col.key + 'Filter';
        return (
            <Dropdown
                onChange={value => {
                    dispatch({ [key]: value });
                    const filter = getFilterState(state, key.replace('Filter', ''), value);
                    if (!filter.length) {
                        var changed = null;
                    } else if (filter.length === 1) {
                        changed = filter[0];
                    } else {
                        changed = filter;
                    }
                    onChange && onChange({ filter: changed });
                }}
                toggle={true}
                value={state[key]}
                indicator={true}
                multiple={col.filterMultiple}
                trigger="click"
                options={col.filter}
                content={col.title}
            />
        );
    }
    if (col.sorter) {
        return (
            <InlineFlex
                onClick={() => {
                    let sortOrder;
                    if (state.sortOrder === 'ascend') {
                        sortOrder = 'descend';
                    } else if (state.sortOrder === 'descend') {
                        sortOrder = undefined;
                    } else {
                        sortOrder = 'ascend';
                    }
                    const payload = { sortKey: col.key, sortOrder };
                    dispatch(payload);
                    onChange && onChange({ sorter: sortOrder && payload });
                }}
            >
                {col.title}
                <SortIcon className={(state.sortKey === col.key && state.sortOrder) || ''} />
            </InlineFlex>
        );
    }
    if (typeof col.title === 'function') {
        return col.title();
    }
    return col.title;
};

const Header = function({ tableProps, columns, state, dispatch, rowData }: IProps) {
    const { showChecker, fixRow, rowId, onChange, pagination = {}, dataSource = [], maxChecked = 100 } = tableProps;
    const [leftOffset, rightOffset, leftFixedIndex, rightFixedIndex] = calcOffsets(columns, !!showChecker);
    const checkFixed = columns[0] && columns[0].fixed === 'left' ? 'fix-left-cell' : '';
    const { page } = getPageInfo(state, pagination);

    const currentPage = state.rowChecked[page - 1] || [];
    const flat = state.rowChecked.reduce((acc: any, val: any) => acc.concat(val), []);
    const totalChecked = flat.filter(Boolean).length;
    const disableCheckAll = totalChecked >= maxChecked;
    return (
        <HeaderRow className={fixRow ? 'header-row-fixed' : ''}>
            {[
                !!showChecker && (
                    <TD key="checker" checker={true} width={70} align="left" className={checkFixed} offset={0}>
                        <Checkbox
                            indeterminate={
                                state.rowChecked.length &&
                                currentPage &&
                                !currentPage.every(Boolean) &&
                                currentPage.some(Boolean)
                            }
                            checked={currentPage && currentPage.length && currentPage.every(Boolean)}
                            onChange={(checkAll: boolean) => {
                                const rowChecked = [...state.rowChecked];
                                if (checkAll) {
                                    if (totalChecked + rowData.length <= maxChecked) {
                                        rowChecked[page - 1] = rowData.map(() => true);
                                    } else {
                                        var count = maxChecked - totalChecked;
                                        if (count > 0) {
                                            rowChecked[page - 1] = rowData.map((checked, idx) => {
                                                if (rowChecked[page - 1][idx]) {
                                                    return true;
                                                } else if (count > 0) {
                                                    count -= 1;
                                                    return true;
                                                }
                                                return false;
                                            });
                                        } else if (!count) {
                                            rowChecked[page - 1] = rowData.map(() => false);
                                        }
                                    }

                                    const flat = rowChecked.reduce((acc, val) => acc.concat(val), []);
                                    dispatch({ rowChecked });
                                    onChange &&
                                        onChange({
                                            checked: dataSource.filter((row, index) => flat[index]).map(r => r[rowId]),
                                        });
                                } else {
                                    rowChecked[page - 1] = rowData.map(() => false);
                                    dispatch({ rowChecked });
                                    onChange && onChange({ checked: [] });
                                }
                            }}
                        />
                    </TD>
                ),
            ].concat(
                columns.map((col: IColumn, index) => {
                    return (
                        <TD
                            align={col.align}
                            key={index}
                            width={col.width}
                            className={mapFixedClass(col.fixed, index === leftFixedIndex || index === rightFixedIndex)}
                            offset={leftOffset.length > index ? leftOffset[index] : rightOffset[index]}
                        >
                            {renderTitle(col, state, dispatch, onChange)}
                        </TD>
                    );
                })
            )}
        </HeaderRow>
    );
};
export default memo(Header);
