// Copyright (C) The Arvados Authors. All rights reserved.
//
// SPDX-License-Identifier: AGPL-3.0

import * as React from "react";
import {
    WithStyles,
    withStyles,
    ButtonBase,
    StyleRulesCallback,
    Theme,
    Popover,
    List,
    ListItem,
    Checkbox,
    ListItemText,
    Button,
    Card,
    CardActions,
    Typography,
    CardContent,
    Tooltip
} from "@material-ui/core";
import * as classnames from "classnames";
import { DefaultTransformOrigin } from "../popover/helpers";
import { createTree, initTreeNode, mapTree } from '~/models/tree';
import { DataTableFilters as DataTableFiltersModel, DataTableFiltersTree } from "./data-table-filters-tree";
import { pipe } from 'lodash/fp';
import { setNode } from '~/models/tree';

export type CssRules = "root" | "icon" | "active" | "checkbox";

const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
    root: {
        cursor: "pointer",
        display: "inline-flex",
        justifyContent: "flex-start",
        flexDirection: "inherit",
        alignItems: "center",
        "&:hover": {
            color: theme.palette.text.primary,
        },
        "&:focus": {
            color: theme.palette.text.primary,
        },
    },
    active: {
        color: theme.palette.text.primary,
        '& $icon': {
            opacity: 1,
        },
    },
    icon: {
        marginRight: 4,
        marginLeft: 4,
        opacity: 0.7,
        userSelect: "none",
        width: 16
    },
    checkbox: {
        width: 24,
        height: 24
    }
});

export interface DataTableFilterItem {
    name: string;
    selected: boolean;
}

export interface DataTableFilterProps {
    name: string;
    filters: DataTableFilterItem[];
    onChange?: (filters: DataTableFilterItem[]) => void;
}

interface DataTableFilterState {
    anchorEl?: HTMLElement;
    filters: DataTableFilterItem[];
    prevFilters: DataTableFilterItem[];
    filtersTree: DataTableFiltersModel;
}

const filters: DataTableFiltersModel = pipe(
    createTree,
    setNode(initTreeNode({ id: 'Project', value: { name: 'Project' } })),
    setNode(initTreeNode({ id: 'Process', value: { name: 'Process' } })),
    setNode(initTreeNode({ id: 'Data collection', value: { name: 'Data collection' } })),
    setNode(initTreeNode({ id: 'General', parent: 'Data collection', value: { name: 'General' } })),
    setNode(initTreeNode({ id: 'Output', parent: 'Data collection', value: { name: 'Output' } })),
    setNode(initTreeNode({ id: 'Log', parent: 'Data collection', value: { name: 'Log' } })),
    mapTree(node => ({...node, selected: true})),
)();

export const DataTableFilters = withStyles(styles)(
    class extends React.Component<DataTableFilterProps & WithStyles<CssRules>, DataTableFilterState> {
        state: DataTableFilterState = {
            anchorEl: undefined,
            filters: [],
            prevFilters: [],
            filtersTree: filters,
        };
        icon = React.createRef<HTMLElement>();

        render() {
            const { name, classes, children } = this.props;
            const isActive = this.state.filters.some(f => f.selected);
            return <>
                <Tooltip title='Filters'>
                    <ButtonBase
                        className={classnames([classes.root, { [classes.active]: isActive }])}
                        component="span"
                        onClick={this.open}
                        disableRipple>
                        {children}
                        <i className={classnames(["fas fa-filter", classes.icon])}
                            data-fa-transform="shrink-3"
                            ref={this.icon} />
                    </ButtonBase>
                </Tooltip>
                <Popover
                    anchorEl={this.state.anchorEl}
                    open={!!this.state.anchorEl}
                    anchorOrigin={DefaultTransformOrigin}
                    transformOrigin={DefaultTransformOrigin}
                    onClose={this.cancel}>
                    <Card>
                        <CardContent>
                            <Typography variant="caption">
                                {name}
                            </Typography>
                        </CardContent>
                        <List dense>
                            {this.state.filters.map((filter, index) =>
                                <ListItem
                                    key={index}>
                                    <Checkbox
                                        onClick={this.toggleFilter(filter)}
                                        color="primary"
                                        checked={filter.selected}
                                        className={classes.checkbox} />
                                    <ListItemText>
                                        {filter.name}
                                    </ListItemText>
                                </ListItem>
                            )}
                        </List>
                        <DataTableFiltersTree
                            filters={this.state.filtersTree}
                            onChange={filtersTree => this.setState({ filtersTree })} />
                        <CardActions>
                            <Button
                                color="primary"
                                variant='contained'
                                size="small"
                                onClick={this.submit}>
                                Ok
                            </Button>
                            <Button
                                color="primary"
                                variant="outlined"
                                size="small"
                                onClick={this.cancel}>
                                Cancel
                            </Button>
                        </CardActions >
                    </Card>
                </Popover>
            </>;
        }

        static getDerivedStateFromProps(props: DataTableFilterProps, state: DataTableFilterState): DataTableFilterState {
            return props.filters !== state.prevFilters
                ? { ...state, filters: props.filters, prevFilters: props.filters }
                : state;
        }

        open = () => {
            this.setState({ anchorEl: this.icon.current || undefined });
        }

        submit = () => {
            const { onChange } = this.props;
            if (onChange) {
                onChange(this.state.filters);
            }
            this.setState({ anchorEl: undefined });
        }

        cancel = () => {
            this.setState(prev => ({
                ...prev,
                filters: prev.prevFilters,
                anchorEl: undefined
            }));
        }

        toggleFilter = (toggledFilter: DataTableFilterItem) => () => {
            this.setState(prev => ({
                ...prev,
                filters: prev.filters.map(filter =>
                    filter === toggledFilter
                        ? { ...filter, selected: !filter.selected }
                        : filter)
            }));
        }
    }
);