import * as React from 'react';
import {
    cx, DataColumnProps, DataTableHeaderCellProps, IDropdownTogglerProps, Overwrite, uuiDataTableHeaderCell, uuiMarkers,
} from '@epam/uui-core';
import {
    DataTableCellContainer,
    DataTableHeaderCell as UuiDataTableHeaderCell,
    HeaderCellContentProps,
} from '@epam/uui-components';
import { ColumnHeaderDropdown } from './ColumnHeaderDropdown';
import { DataTableHeaderCellMods } from './types';
import { IconButton } from '../buttons';
import { Checkbox, CheckboxProps } from '../inputs';
import { Tooltip } from '../overlays';
import { Text, TextProps } from '../typography';
import { ReactComponent as DefaultSortIcon } from '@epam/assets/icons/table-swap-outline.svg';
import { ReactComponent as SortIcon } from '@epam/assets/icons/table-sort_asc-outline.svg';
import { ReactComponent as SortIconDesc } from '@epam/assets/icons/table-sort_desc-outline.svg';
import { ReactComponent as FilterIcon } from '@epam/assets/icons/content-filtration-fill.svg';
import { ReactComponent as DropdownIcon } from '@epam/assets/icons/navigation-chevron_down-outline.svg';
import { ReactComponent as OpenedDropdownIcon } from '@epam/assets/icons/navigation-chevron_up-outline.svg';
import { ReactComponent as FoldIcon } from '@epam/assets/icons/navigation-collapse_all-outline.svg';
import { ReactComponent as UnfoldIcon } from '@epam/assets/icons/navigation-expand_all-outline.svg';
import { i18n } from '../../i18n';
import { settings } from '../../settings';

import './variables.scss';
import css from './DataTableHeaderCell.module.scss';

interface DataTableHeaderCellState {
    isDropdownOpen: boolean;
}

export interface DataTableHeaderCellModsOverride {
}

export class DataTableHeaderCell<TItem, TId> extends
    React.Component<
    DataTableHeaderCellProps<TItem, TId> & Overwrite<DataTableHeaderCellMods,
    DataTableHeaderCellModsOverride>,
    DataTableHeaderCellState
    > {
    state: DataTableHeaderCellState = {
        isDropdownOpen: null,
    };

    getTooltipContent = (column: DataColumnProps<TItem, TId>) => (
        <div className={ cx(css.cellTooltipWrapper, uuiDataTableHeaderCell.uuiTableHeaderCaptionTooltip) }>
            <Text cx={ [css.cellTooltipText, css.tooltipCaption] }>
                { column.caption }
            </Text>
            { column.info && (
                <Text cx={ [css.cellTooltipText, css.tooltipInfo] }>
                    { column.info }
                </Text>
            ) }
        </div>
    );

    getColumnCaption = () => {
        const renderTooltip = this.props.column.renderTooltip || this.getTooltipContent;
        const captionCx = [
            css.caption,
            this.props.textCase === 'upper' && css.upperCase,
            uuiDataTableHeaderCell.uuiTableHeaderCaption,
            settings.sizes.dataTable.header.row.cell.truncate.includes(this.props.size) && css.truncate,
        ];

        return (
            <div
                className={ cx(css.captionWrapper, css['align-' + this.props.column.textAlign], uuiDataTableHeaderCell.uuiTableHeaderCaptionWrapper) }
            >
                <Tooltip
                    placement="top"
                    color="inverted"
                    content={ renderTooltip(this.props.column) }
                    cx={ css.cellTooltip }
                    openDelay={ 600 }
                >
                    <Text
                        key="text"
                        fontSize={ settings.sizes.dataTable.header.row.cell.columnCaption[this.props.textCase === 'upper' ? 'uppercase' : 'fontSize'] as TextProps['fontSize'] }
                        size={ settings.sizes.dataTable.header.row.cell.columnCaption.size as TextProps['size'] }
                        cx={ captionCx }
                    >
                        { this.props.column.caption }
                    </Text>
                </Tooltip>
                { this.props.column.isSortable && (!this.props.column.renderFilter || this.props.sortDirection) && (
                    <IconButton
                        key="sort"
                        cx={ cx(css.icon, css.sortIcon, this.props.sortDirection && css.sortIconActive, uuiDataTableHeaderCell.uuiTableHeaderSortIcon) }
                        color={ this.props.sortDirection ? 'neutral' : 'secondary' }
                        icon={ this.props.sortDirection === 'desc' ? SortIconDesc : this.props.sortDirection === 'asc' ? SortIcon : DefaultSortIcon }
                    />
                ) }
                { this.props.isFilterActive && (
                    <IconButton
                        key="filter"
                        cx={ cx(css.icon, !this.props.sortDirection && css.filterIcon, uuiDataTableHeaderCell.uuiTableHeaderFilterIcon) }
                        color="neutral"
                        icon={ FilterIcon }
                    />
                ) }
                { this.props.column.renderFilter && (
                    <IconButton
                        key="dropdown"
                        cx={ cx(css.icon, css.dropdownIcon, uuiDataTableHeaderCell.uuiTableHeaderDropdownIcon) }
                        color="secondary"
                        icon={ this.state.isDropdownOpen ? OpenedDropdownIcon : DropdownIcon }
                    />
                ) }
            </div>
        );
    };

    renderHeaderCheckbox = () => {
        if (this.props.selectAll && this.props.isFirstColumn) {
            return (
                <Checkbox
                    size={ settings.sizes.dataTable.header.row.cell.checkbox[this.props.size] as CheckboxProps['size'] }
                    { ...this.props.selectAll }
                    cx={ cx(css.checkbox, uuiDataTableHeaderCell.uuiTableHeaderCheckbox) }
                />
            );
        }
    };

    renderFoldAllIcon = () => {
        if (this.props.isFirstColumn && this.props.showFoldAll) {
            return (
                <Tooltip content={
                    this.props.areAllFolded
                        ? i18n.tables.columnHeader.expandAllTooltip
                        : i18n.tables.columnHeader.collapseAllTooltip
                }
                >
                    <IconButton
                        color="secondary"
                        cx={ cx(css.icon, css.foldAllIcon, uuiDataTableHeaderCell.uuiTableHeaderFoldAllIcon) }
                        icon={ this.props.areAllFolded ? UnfoldIcon : FoldIcon }
                        onClick={ this.props.onFoldAll }
                        rawProps={ {
                            'aria-label': this.props.areAllFolded ? 'Expand All' : 'Collapse All',
                            'aria-expanded': !!this.props.areAllFolded,
                        } }
                    />
                </Tooltip>
            );
        }
    };

    renderResizingMarker = (props: HeaderCellContentProps) => {
        return (
            <div
                role="separator"
                onMouseDown={ props.onResizeStart }
                className={ cx(css.resizingMarker, uuiMarkers.draggable, uuiMarkers.clickable) }
            />
        );
    };

    getLeftPadding = () => {
        const { columnsGap, isFirstColumn } = this.props;

        if (columnsGap) return isFirstColumn ? columnsGap : +columnsGap / 2;
        return isFirstColumn ? settings.sizes.dataTable.header.row.cell.defaults.paddingEdge : settings.sizes.dataTable.header.row.cell.defaults.padding;
    };

    getRightPadding = () => {
        const { columnsGap, isLastColumn } = this.props;

        if (columnsGap) return isLastColumn ? columnsGap : +columnsGap / 2;
        return isLastColumn ? settings.sizes.dataTable.header.row.cell.defaults.paddingEdge : settings.sizes.dataTable.header.row.cell.defaults.padding;
    };

    getResizingMarkerWidth = () => {
        const { columnsGap } = this.props;
        return columnsGap ? +columnsGap / 2 : settings.sizes.dataTable.header.row.cell.defaults.resizeMarker;
    };

    renderCellContent = (props: HeaderCellContentProps, dropdownProps?: IDropdownTogglerProps) => {
        const isResizable = this.props.column.allowResizing ?? this.props.allowColumnsResizing;
        const onClickEvent = !props.isResizing && (!this.props.column.renderFilter ? props.toggleSort : dropdownProps?.onClick);

        const computeStyles = {
            '--uui-dt-header-cell-icon-size': `${settings.sizes.dataTable.header.row.cell.iconSize[this.props.size || settings.sizes.dataTable.header.row.cell.defaults.size]}px`,
            '--uui-dt-header-cell-padding-start': `${this.getLeftPadding()}px`,
            '--uui-dt-header-cell-padding-end': `${this.getRightPadding()}px`,
            '--uui-dt-header-cell-resizing-marker-width': `${this.getResizingMarkerWidth()}px`,
        } as React.CSSProperties;

        return (
            <DataTableCellContainer
                column={ this.props.column }
                ref={ (ref) => {
                    (props.ref as React.RefCallback<HTMLElement>)(ref);
                    (dropdownProps?.ref as React.RefCallback<HTMLElement>)?.(ref);
                } }
                cx={ cx(
                    uuiDataTableHeaderCell.uuiTableHeaderCell,
                    (this.props.column.isSortable || this.props.isDropdown) && uuiMarkers.clickable,
                    css.root,
                    `uui-size-${this.props.size || settings.sizes.dataTable.header.row.cell.defaults.size}`,
                    this.props.isFirstColumn && 'uui-dt-header-first-column',
                    this.props.isLastColumn && 'uui-dt-header-last-column',
                    this.props.column.fix && css['pinned-' + this.props.column.fix],
                    isResizable && css.resizable,
                    props.isDraggable && css.draggable,
                    props.isDragGhost && css.ghost,
                    props.isDraggedOut && css.isDraggedOut,
                    props.isDndInProgress && css['dnd-marker-' + props.position],
                ) }
                onClick={ onClickEvent }
                rawProps={ {
                    role: 'columnheader',
                    'aria-sort': this.props.sortDirection === 'asc' ? 'ascending' : this.props.sortDirection ? 'descending' : 'none',
                    ...props.eventHandlers,
                } }
                style={ computeStyles }
            >
                { this.renderHeaderCheckbox() }
                { this.renderFoldAllIcon() }
                { this.getColumnCaption() }
                { isResizable && this.renderResizingMarker(props) }
            </DataTableCellContainer>
        );
    };

    renderCellWithFilter = (props: HeaderCellContentProps) => (
        <ColumnHeaderDropdown
            isOpen={ this.state.isDropdownOpen }
            isSortable={ this.props.column.isSortable }
            renderTarget={ (dropdownProps) => this.renderCellContent(props, dropdownProps) }
            renderFilter={ this.props.renderFilter }
            onSort={ this.props.onSort }
            sortDirection={ this.props.sortDirection }
            onOpenChange={ (isDropdownOpen) => this.setState({ isDropdownOpen }) }
            title={ this.props.column.caption as string }
        />
    );

    render() {
        if (this.props.column.renderHeaderCell) {
            return this.props.column.renderHeaderCell(this.props);
        }

        return (
            <UuiDataTableHeaderCell
                { ...this.props }
                renderCellContent={ this.props.column.renderFilter ? this.renderCellWithFilter : this.renderCellContent }
            />
        );
    }
}
