import React from 'react';
import { Definition } from 'sync-ql';
import {
    Button,
} from '@mui/material';
import {
    DataFilterSet,
    DataFilterType,
    DataFilterOperation,
    FiltersMessage,
    DataOption,
    FiltersStore,
    ExternalFilter
} from '../types/filter.type';
import { FilterActionsContainer, FiltersContainer } from './style';
import { DataTableFilter, operationsConstrains } from './filter';
import { DataColumnExtra } from '../types/table.type';

export interface DataTableFiltersProps {
    filters: FiltersStore,
    external: ExternalFilter,
    columns: DataColumnExtra[]
    messages: FiltersMessage,
    onChange: (filters: FiltersStore) => void,
    onExternalChange: (filter: ExternalFilter) => void,
    onApply: (filters: FiltersStore) => void,
    onClose: () => void
}

export const DataTableFilters: React.FC<DataTableFiltersProps> = ({ filters: filtersStore, external, columns, messages, onChange, onExternalChange, onApply, onClose }) => {
    const getFilterOperation = (column: { name: string, type: DataFilterSet | 'none' }) => {
        let result = filtersStore[column.name] && filtersStore[column.name].operation
            ? filtersStore[column.name].operation
            : column.type === 'date'
                ? 'between'
                : column.type === 'text' || column.type === 'set'
                    ? 'auto'
                    : 'equal'
        if (!operationsConstrains[column.type][result]) {
            result = Object.keys(operationsConstrains[column.type])[0] as Definition;
        }
        return result;
    }

    const getFilterRange = (column: { name: string }) => {
        return filtersStore[column.name]
            ? filtersStore[column.name].range
            : undefined
    }

    const getFilterValue = (column: { name: string }) => {
        return filtersStore[column.name]
            ? filtersStore[column.name].value
            : null
    }

    const handleFilterChange = (column: { name: string }) =>
        (operation: DataFilterOperation, value: DataFilterType | [DataFilterType, DataFilterType]) => {
            onChange({
                ...filtersStore,
                [column.name]: {
                    operation,
                    value: value
                }
            })
        }
    const handleExternalFilterChange =
        (operation: DataFilterOperation, value: DataFilterType | [DataFilterType, DataFilterType]) => {
            onExternalChange({
                ...external,
                operation,
                value: value
            })
        }
    const handleFilterOptionsLoad =
        (column: { options?: (text: string) => Promise<DataOption[]> }) =>
            async (inputText: string): Promise<DataOption[]> => {
                if (column.options) {
                    return await column.options(inputText);
                }
                return []
            }
    const handleExternalFilterOptionsLoad =
        async (inputText: string): Promise<DataOption[]> => {
            if (external.options) {
                return await external.options(inputText);
            }
            return []
        }
    const handleApplyFilters = () => {
        const filters: FiltersStore = {};

        Object.keys(filtersStore).forEach(key => {
            filters[key] = { ...filtersStore[key] }
        })
        onApply(filters);
    }
    const handleClose = () => {
        onClose();
    }

    return (
        <>
            <FiltersContainer>
                <table style={{ width: 'calc(100% - 32px)' }}>
                    <tbody>
                        {
                            external &&
                            <DataTableFilter
                                type={external.type}
                                label={''}
                                messages={messages}
                                operation={external.operation}
                                range={external.range}
                                value={external.value ?? ''}
                                onChange={handleExternalFilterChange}
                                onOptionsLoad={handleExternalFilterOptionsLoad} />
                        }
                        {
                            columns.map(column => (
                                !column.hidden && column.type !== 'none' &&
                                <DataTableFilter
                                    key={column.name}
                                    type={column.type}
                                    label={column.label ?? ''}
                                    messages={messages}
                                    operation={getFilterOperation(column)}
                                    range={getFilterRange(column)}
                                    value={getFilterValue(column)}
                                    onChange={handleFilterChange(column)}
                                    onOptionsLoad={handleFilterOptionsLoad(column)} />
                            ))
                        }
                    </tbody>
                </table>
            </FiltersContainer>
            <FilterActionsContainer>
                <Button color="primary" style={{ marginLeft: '64px' }} onClick={handleApplyFilters}>
                    {messages.applyFilters}
                </Button>
                <Button style={{ marginRight: '80px' }} onClick={handleClose}>
                    {messages.closeFilters}
                </Button>
            </FilterActionsContainer>
        </>
    )
}
