import * as React from 'react';

import {
    getParentElmtByClassName,
    getRelativeBoundingClientRect,
} from '../../../mmui-util';
import { RefinerProps, RefinerState } from './utils';
import { ColumnNumericalRefinerComponent } from './ColumnNumericalRefinerComponent';
import { ColumnCategoricalRefinerComponent } from './ColumnCategoricalRefinerComponent';
import { ColumnDateRefinerComponent } from './ColumnDateRefinerComponent';
import { ColumnChoiceRefinerComponent } from './ColumnChoiceRefinerComponent';

/**
 * Column Head Component to add sorting and filter functionality to table columns.
 * This Component
 */
export class ColumnHeadComponent extends React.Component<
    RefinerProps,
    RefinerState
> {
    hasRowLevels;

    private static id_counter = 0;
    protected id;

    /**
     * Generate a unique id for this component instance
     */
    protected getId(): number {
        if (this.id === undefined) {
            this.id = ColumnHeadComponent.id_counter;
            ColumnHeadComponent.id_counter++;
        }
        return this.id;
    }

    constructor(props) {
        super(props);
        this.hasRowLevels = false;
        if (props.hasRowLevels) {
            this.hasRowLevels = true;
        }

        this.state = {
            id: 'mmui_column_head_' + this.getId(),
            filterPanelMode: 'closed',
            isFiltered: false,
            filterPanelLayout: { align: 'right' },
        };
    }

    setIsFiltered = (isFiltered: boolean) => {
        this.setState({ isFiltered });
    };

    /**
     * Handles clicks to change the sort order of the column.
     * @param evt
     */
    handleSortOrderChange(evt) {
        evt.preventDefault();

        let config = this.props.config,
            transforms = this.props.transforms,
            orderColumn =
                config.columnName == 'pivot'
                    ? config.rowKey
                    : config.columnName,
            orderMethod = 'ASC';
        if (transforms.order) {
            if (transforms.order.column === orderColumn) {
                orderMethod =
                    transforms.order.method === 'ASC' ? 'DESC' : 'ASC';
            }
        } else if (this.props.preSort === 'ASC') {
            orderMethod = 'DESC';
        }

        transforms.order = {
            column: orderColumn,
            method: orderMethod,
            ignoreCase: config.orderIgnoreCase ? true : false,
            emptyLocation: config.orderEmptyLocation,
        };

        this.props.setTransforms(transforms);
    }

    /**
     * Handles clicks to toggle the visibility of the filter panel.
     * @param evt
     */
    handlePanelBtnClick(evt) {
        // let config = this.props.config,
        //     transforms = this.props.transforms,
        //     panels = transforms.panels,
        //     filterPanel = panels[config.columnName],
        //     value = evt.target.value
        // ;

        evt.preventDefault();

        let parentElmt = getParentElmtByClassName(
            evt.currentTarget,
            'table-responsive'
        );
        if (parentElmt === undefined || parentElmt === null) {
            parentElmt = getParentElmtByClassName(
                evt.currentTarget,
                'mmui-table'
            );
        }

        const filterPanelLayout = { align: 'left' };
        if (parentElmt) {
            const childRect = evt.currentTarget.getBoundingClientRect();
            const parentRect = parentElmt.getBoundingClientRect();
            const relativeRect = getRelativeBoundingClientRect(
                childRect,
                parentRect
            );
            if (Math.abs(relativeRect.left) > Math.abs(relativeRect.right)) {
                filterPanelLayout.align = 'right';
            }
        }

        let filterPanelMode = this.state.filterPanelMode;
        if (filterPanelMode === undefined || filterPanelMode === 'closed') {
            filterPanelMode = 'open';
        } else {
            filterPanelMode = 'closed';
        }

        this.setState({
            filterPanelMode: filterPanelMode,
            filterPanelLayout: filterPanelLayout,
        });

        // transforms.panels[config.columnName] = filterPanel;
        // this.props.setTransforms(transforms);
    }

    onBlur = () => {
        if (this.state.filterPanelMode === 'open') {
            let elmt = event.target as HTMLElement,
                isFilterPanelClick = false;
            while (elmt) {
                isFilterPanelClick =
                    isFilterPanelClick || elmt.id === this.state.id;
                if (isFilterPanelClick) {
                    break;
                }
                elmt = elmt.parentElement;
            }

            if (!isFilterPanelClick) {
                this.setState({ filterPanelMode: 'closed' });
            }
        }
    };

    componentDidMount(): void {
        document.addEventListener('click', this.onBlur);
    }

    componentWillUnmount(): void {
        document.removeEventListener('click', this.onBlur);
    }

    /**
     * Render Column Head Component
     */
    render() {
        let classNameArray = [],
            thClassNameArray = [],
            thColumnClassNameArray = ['mmui-th-column'],
            nameClassNameArray = [],
            nameElmt = null,
            sortSymbol = null,
            selectionElmt,
            refinerBtnElmt,
            toolTipElement,
            filterPanelComponent = null,
            config = this.props.config,
            data = this.props.data,
            transforms = this.props.transforms,
            orderUrl = `?order_column=${config.columnName}`,
            filterBtnStyle: any = {},
            filterPanelComponentStyle: any = { display: 'none' };
        if (this.props.isSelectionColumn) {
            selectionElmt = (
                <div className="mmui-selection">
                    <input
                        className="form-check-input"
                        type="checkbox"
                        checked={this.props.isSelected}
                        ref={(el) =>
                            el &&
                            (el.indeterminate = this.props.isIndeterminate)
                        }
                        onChange={this.props.onSelectionClick}
                    />
                </div>
            );

            if (config.hasLevels) {
                thColumnClassNameArray.push('mmui-pl-3');
            }
        } else if (config.hasLevels) {
            thColumnClassNameArray.push('mmui-pl-3');
        }

        if (config.isNumeric || config.isMetric) {
            thClassNameArray.push('text-right');
            nameClassNameArray.push('mmui-th-metric');
        }
        if (config.hasTooltip) {
            toolTipElement = <i className="fa fa-info-circle mmui-popover-icon"
                         data-toggle="popover" data-content={config.toolTipInfo}
                         data-placement="top"> </i>
        }
        if (config.hasFilter) {
            thClassNameArray.push('mmui-refiner');

            const filterIconStyleArray = ['fa', 'fa-filter'];
            if (this.state.isFiltered) {
                filterIconStyleArray.push('background-core-brand-blue-90');
                filterIconStyleArray.push('color-neutral-white');
            }
            refinerBtnElmt = (
                <a
                    href="#"
                    className="btn mmui-refiner-btn"
                    role="button"
                    style={filterBtnStyle}
                    onClick={this.handlePanelBtnClick.bind(this)}
                >
                    <i className={filterIconStyleArray.join(' ')}></i>
                </a>
            );
        }
        const hasTranformOrder =
            transforms.order && transforms.order.column === config.columnName;
        if (this.props.preSort || hasTranformOrder) {
            let orderMethod = this.props.preSort;
            if (transforms.order && transforms.order.method) {
                orderMethod = transforms.order.method;
            }
            classNameArray.push('active');
            if (orderMethod == 'ASC') {
                sortSymbol = <i className="fas fa-caret-up"></i>;
            } else {
                sortSymbol = <i className="fas fa-caret-down"></i>;
            }

            orderUrl = orderUrl + `&order_method=${orderMethod}`;
        }

        /**
         * Set the filterPanelComponent based on the config.dataType.
         */
        if (config.hasFilter && config.dataType) {
            let isExtentEmpty = false;
            if (data && data.extent) {
                isExtentEmpty =
                    (data.extent != undefined && data.extent?.length == 0) ||
                    (data.extent?.length == 1 && data.extent[0] == '');
            }
            switch (config.dataType) {
                case 'datetime':
                    filterPanelComponent = (
                        <ColumnDateRefinerComponent
                            config={config}
                            transforms={transforms}
                            setTransforms={this.props.setTransforms}
                            transformsDelay={this.props.transformsDelay}
                            setIsFiltered={this.setIsFiltered}
                        />
                    );
                    break;
                case 'categorical':
                    if (isExtentEmpty) {
                        refinerBtnElmt = null;
                    }
                    filterPanelComponent = (
                        <ColumnCategoricalRefinerComponent
                            config={config}
                            transforms={transforms}
                            setTransforms={this.props.setTransforms}
                            transformsDelay={this.props.transformsDelay}
                            setIsFiltered={this.setIsFiltered}
                        />
                    );
                    break;
                case 'choice':
                    if (isExtentEmpty) {
                        refinerBtnElmt = null;
                    }
                    filterPanelComponent = (
                        <ColumnChoiceRefinerComponent
                            config={config}
                            data={data}
                            transforms={transforms}
                            setTransforms={this.props.setTransforms}
                            transformsDelay={this.props.transformsDelay}
                            setIsFiltered={this.setIsFiltered}
                            componentHeadId={this.getId()}
                        />
                    );
                    break;
                case 'numerical':
                    filterPanelComponent = (
                        <ColumnNumericalRefinerComponent
                            config={config}
                            data={data}
                            transforms={transforms}
                            setTransforms={this.props.setTransforms}
                            transformsDelay={this.props.transformsDelay}
                            setIsFiltered={this.setIsFiltered}
                            displayDefaultLabel={this.props.displayDefaultLabel}
                        />
                    );
                    break;
                default:
                    if (isExtentEmpty) {
                        refinerBtnElmt = null;
                    }
                    filterPanelComponent = (
                        <ColumnCategoricalRefinerComponent
                            config={config}
                            transforms={transforms}
                            setTransforms={this.props.setTransforms}
                            transformsDelay={this.props.transformsDelay}
                            setIsFiltered={this.setIsFiltered}
                        />
                    );
                    break;
            }
        }

        if (config.isSortable) {
            nameElmt = (
                <div className={classNameArray.join(' ')}>
                    <a
                        href={orderUrl}
                        onClick={this.handleSortOrderChange.bind(this)}
                    >
                        {config.name}
                    </a>
                </div>
            );
        } else {
            nameElmt = <div>{config.name}</div>;
        }

        filterPanelComponentStyle.display =
            this.state.filterPanelMode === 'open' ? 'block' : 'none';

        if (this.state.filterPanelLayout.align == 'right') {
            filterPanelComponentStyle.right = 0;
        } else {
            filterPanelComponentStyle.left = 0;
        }

        return (
            <th
                id={this.state.id}
                key={config.key}
                colSpan={config.colSpan}
                className={thClassNameArray.join(' ')}
            >
                <div className={nameClassNameArray.join(' ')}>
                    <div className="d-flex flex-row">
                        {selectionElmt}
                        {refinerBtnElmt}
                        {nameElmt}
                        {toolTipElement}
                        {sortSymbol}
                    </div>
                    <div className="mmui-table-refiner-panel">
                        <div
                            className="mmui-table-refiner-component card"
                            style={filterPanelComponentStyle}
                        >
                            <div className="card-body pb-0">
                                {filterPanelComponent}
                            </div>
                        </div>
                    </div>
                </div>
            </th>
        );
    }
}
