import React from 'react';
import AsyncData from '../shared/AsyncData';
import { Table, TableBody, TableRow, TableCell, Paper, TableHead, Fab, TextField, Button, TableSortLabel } from '@material-ui/core';
import AddIcon from '@material-ui/icons/Add';
import TableFooter from '@material-ui/core/TableFooter';
import TablePagination from '@material-ui/core/TablePagination';
import FilterIcon from '@material-ui/icons/FilterList';
import appConstants from '../../appConstants';
import EntityTableRow from '../shared/EntityTableRow';
import queryString from 'query-string';
import { useLocalStorage } from '../../hooks/useLocalStorage';
import useDeepState from '../../hooks/useDeepState';
import { CustomizedComponent } from '../../utils/utils';

const Pagination = ({ paginationResult, rowsPerPage, setRowsPerPage, changePage }) => {
    if (!paginationResult) return null;

    const { totalItems, currentPage } = paginationResult;
    console.log('TCL: Pagination -> totalItems', totalItems);
    return (
        <TableRow css={{ padding: 0 }}>
            <TablePagination
                css={{ border: 'none', margin: 0, padding: 0 }}
                rowsPerPageOptions={[25, 50, 100]}
                count={totalItems || 0}
                rowsPerPage={rowsPerPage || 0}
                page={currentPage || 0}
                SelectProps={{
                    native: true
                }}
                onChangePage={(_, newPage) => changePage(newPage)}
                onChangeRowsPerPage={(e) => setRowsPerPage(e.target.value)}
            />
        </TableRow>
    );
};

const SortingRow = ({ entityTypes, defaultSorting = {}, onSortingChange, onToggleFilter }) => {
    return (
        <TableRow css={{ backgroundColor: '#dce3e2' }}>
            <TableCell css={{ width: 80, border: 'none' }}>
                <Button variant="outlined" color="primary" onClick={onToggleFilter}>
                    <FilterIcon />
                    Filter
                </Button>
            </TableCell>
            {entityTypes.map((p) => (
                <TableCell key={p} css={{ border: 'none' }} sortDirection={false}>
                    <TableSortLabel
                        css={{ textTransform: 'uppercase', fontWeight: 600 }}
                        active={defaultSorting.field === p}
                        direction={defaultSorting.isAscending ? 'asc' : 'desc'}
                        onClick={() => onSortingChange(p, defaultSorting.isAscending ? 'desc' : 'asc')}>
                        {p}
                    </TableSortLabel>
                </TableCell>
            ))}
        </TableRow>
    );
};

const FilterRow = ({ entityTypes, onFilterChange, defaultFilters }) => {
    const [filters, setFilters] = React.useState(defaultFilters);
    React.useEffect(() => {
        setFilters(defaultFilters.reduce((o, key) => ({ ...o, [key.field]: key.value }), {}));
    }, [defaultFilters]);

    const setFilter = (id, newValue) => {
        setFilters((prev) => ({ ...prev, [id]: newValue }));
    };

    const filterChanged = () => {
        onFilterChange(
            Object.keys(filters)
                .filter((f) => filters[f])
                .map((f) => ({ field: f, value: filters[f] }))
        );
    };

    return (
        <TableRow css={{ transition: 'all 1s' }}>
            <TableCell css={{ width: 80 }}>
                <Button variant="outlined" color="primary" onClick={filterChanged}>
                    <FilterIcon />
                    Apply
                </Button>
            </TableCell>
            {entityTypes.map((p) => (
                <TableCell key={p}>
                    <TextField
                        value={filters[p] || ''}
                        onKeyPress={(event) => {
                            if (event.key === 'Enter') {
                                filterChanged();
                            }
                        }}
                        onChange={(e) => setFilter(p, e.target.value)}
                        margin={'dense'}
                        variant={'outlined'}
                        placeholder={p}
                    />
                </TableCell>
            ))}
        </TableRow>
    );
};

const EntityList = ({ history, location, match }) => {
    const entityId = history.location.pathname.slice(1);
    const entityData = appConstants.entities.find((e) => e.id === entityId);

    const [dataChangeTracker, setDataChangeTracker] = React.useState(0);
    const [paginationResult, setPaginationResult] = useDeepState({});
    const [filterDisplayed, setFilterDisplayed] = useDeepState(false);

    const [rowsPerPage, setRowsPerPage] = useLocalStorage(25);

    const parsedQuery = queryString.parse(location.search);

    const currentPage = (parsedQuery.page && parseInt(parsedQuery.page)) || 0;
    const currentFilters = Object.keys(parsedQuery)
        .filter((q) => q.startsWith('filter-'))
        .map((q) => ({ field: q.split('-')[1], value: parsedQuery[q] }));

    const currentSorting = {
        field: parsedQuery.sortBy, // || Object.keys(entityData.schema)[0],
        isAscending: parsedQuery.orderBy !== 'desc'
    };

    const changePage = (newPage) => {
        history.push({ pathname: history.location.pathname, search: newPage === 0 ? null : `?page=${newPage}` });
    };

    const changeFilter = (newFilters) => {
        history.push({
            pathname: history.location.pathname,
            search: `?${newFilters.map((f) => `filter-${f.field}=${f.value}`).join('&')}`
        });
    };

    const changeSorting = (field, isAscending) => {
        history.push({
            pathname: history.location.pathname,
            search: `?sortBy=${field}&orderBy=${isAscending}`
        });
    };

    return (
        <CustomizedComponent customizationName="list" entityName={entityId}>
            <Paper css={{ position: 'relative' }}>
                <Fab
                    onClick={() => history.push(`/${entityId}/new`)}
                    css={{ position: 'absolute', left: 16, top: -16, zIndex: 100 }}
                    color="primary"
                    aria-label="Add">
                    <AddIcon />
                </Fab>
                <Table>
                    <TableHead>
                        <Pagination
                            paginationResult={paginationResult}
                            rowsPerPage={rowsPerPage}
                            setRowsPerPage={setRowsPerPage}
                            changePage={changePage}
                        />
                        {filterDisplayed && (
                            <CustomizedComponent
                                customizationName="filter"
                                entityName={entityId}
                                renderProperties={{ onFilterChange: changeFilter, currentFilters: currentFilters }}>
                                <FilterRow
                                    defaultFilters={currentFilters}
                                    entityTypes={Object.keys(entityData.schema)}
                                    onFilterChange={changeFilter}
                                />
                            </CustomizedComponent>
                        )}
                        <SortingRow
                            onToggleFilter={() => setFilterDisplayed(!filterDisplayed)}
                            defaultSorting={currentSorting}
                            entityTypes={Object.keys(entityData.schema)}
                            onSortingChange={changeSorting}
                        />
                    </TableHead>
                    <AsyncData
                        renderData={(result) => {
                            setPaginationResult(result.paginationResult);
                            return (
                                <CustomizedComponent customizationName="tableBody" entityName={entityId} renderProperties={result.data}>
                                    <TableBody>
                                        {result.data.map((rowData, index) => (
                                            <CustomizedComponent
                                                customizationName="tableRow"
                                                entityName={entityId}
                                                renderProperties={rowData}>
                                                <EntityTableRow
                                                    d={rowData}
                                                    isEven={index % 2 === 0}
                                                    data={result.data}
                                                    dataChanged={() => setDataChangeTracker(dataChangeTracker + 1)}
                                                    entityData={entityData}
                                                    entityId={entityId}
                                                    history={history}
                                                    key={rowData.id}
                                                />
                                            </CustomizedComponent>
                                        ))}
                                    </TableBody>
                                </CustomizedComponent>
                            );
                        }}
                        path={'fetchAll'}
                        dataChangeTracker={dataChangeTracker}
                        requestData={[
                            entityId,
                            {
                                paginationOptions: { rowCount: rowsPerPage, currentPage: currentPage },
                                filters: currentFilters,
                                sortOptions: currentSorting
                            }
                        ]}
                    />
                    <TableFooter>
                        <Pagination
                            paginationResult={paginationResult}
                            rowsPerPage={rowsPerPage}
                            setRowsPerPage={setRowsPerPage}
                            changePage={changePage}
                        />
                    </TableFooter>
                </Table>
            </Paper>
        </CustomizedComponent>
    );
};

export default EntityList;
