/**
 * empty comment line Ivan Marshalkin
 *
 * @author: Ivan Marshalkin
 * @date: 2019-04-26
 */

import * as React from 'react';
import {Button, Icon, joinClassNames, PLACEMENT, SIZE, Tooltip} from '../../index';
import {Resizer} from '../resizer/Resizer';

import * as styles from './cardPanel.m.scss';
import {CardPanelGrid} from './CardPanelGrid';
import {CardPanelGroup} from './CardPanelGroup';

type CardPanelTheme = 'default' | 'dark';

export type CardPanelFlexDirection =
    'column' | // default value. render all children in column
    'row' | // add flex to content, every children will be rendered in one row
    'row-wrap' | // add grid to content. if @media < 1320, one column, if @media >= 1320 to columns (minmax(435px, 695px) minmax(435px, 695px))
    'row-resizable'; // the same as 'row', but add resizable for first element

export type ResizerOptions = {
    minWidth?: number;
    maxWidth?: number;
}

export interface ICardPanelProps {
    children?: React.ReactNode;
    title?: React.ReactNode;
    titleTooltip?: string;
    internal?: boolean; // Minimalistic header
    isCollapsed?: boolean;
    hideOverflow?: boolean;
    leftExtraItems?: React.ReactNode;
    rightExtraItems?: React.ReactNode;
    noBodyPadding?: boolean;
    contentAutoHeight?: boolean;
    'data-qaid'?: string;
    'data-panel-id'?: string;
    onToggleCollapse?: (isCollapsed: boolean) => void;
    mountOnExpand?: boolean; // we mount children only when we open the panel
    theme?: CardPanelTheme;
    flexDirection?: CardPanelFlexDirection;
    isSticky?: boolean;
    isWide?: boolean; // by default, max-width of CardPanel is 695px, if isWide === true, width is 100%
    forwardRef?: React.RefObject<HTMLDivElement>;
    resizerOptions?: ResizerOptions;
    helperText?: React.ReactNode;
    helperTitle?: string;
}

interface IState {
    isCollapsed: boolean;
    isShowHelp: boolean;
}

const defaultProps = {
    hideOverflow: false
};

export class CardPanel extends React.Component<ICardPanelProps, IState> {
    static Group = CardPanelGroup;
    static Grid = CardPanelGrid;
    static defaultProps = defaultProps;

    private minResizerWidth?: number;

    DEFAULT_RESIZABLE_CONTENT_WIDTH = 400;

    resizerColumnRef = React.createRef<HTMLDivElement>();

    override state: IState = {
        isCollapsed: true,
        isShowHelp: this.props.helperText ? true : false
    };

    // public api
    expand () {
        this.setState({isCollapsed: false});
    }

    get drawHeader () {
        return this.props.leftExtraItems || this.props.title || this.props.rightExtraItems;
    }

    get rightItems () {
        const {rightExtraItems, isCollapsed} = this.props;

        return (
            <React.Fragment>
                {rightExtraItems && rightExtraItems}
                {isCollapsed !== undefined && (
                    <div
                        className={styles.collapseIcon}
                        onClick={this.handleCollapseClick}
                        style={{transform: this.state.isCollapsed ? 'rotate(-90deg)' : ''}}
                    >
                        <Icon name='chevron-down'/>
                    </div>
                )}
            </React.Fragment>
        );
    }

    get renderContent () {
        const {
            internal,
            noBodyPadding,
            contentAutoHeight,
            title,
            leftExtraItems,
            rightExtraItems,
            flexDirection
        } = this.props;

        const classNames = joinClassNames(
            styles.cardContent,
            [styles.internal, internal === true],
            [styles.noBodyPadding, noBodyPadding === true],
            [styles.noOverflow, this.props.hideOverflow === true],
            [styles.contentAutoHeight, contentAutoHeight === true],
            [styles.isCollapsed, this.state.isCollapsed === true],
            [styles.withoutHeader, !title && !leftExtraItems && !rightExtraItems],
            [styles.flexRow, flexDirection === 'row' || flexDirection === 'row-wrap' || flexDirection === 'row-resizable'],
            [styles.flexColumn, flexDirection === 'column'],
            [styles.flexWrap, flexDirection === 'row-wrap'],
            'scrollable'
        );

        let children = this.props.children;

        if (flexDirection === 'row-resizable') {
            children = React.Children.map(this.props.children, (child, index) => {
                const childStyles = joinClassNames(
                    styles.childContainer,
                    [styles.resizableContainer, index === 0]
                );

                if (index === 0) {
                    return (
                        <>
                            <div className={childStyles} ref={this.resizerColumnRef}>
                                {child}
                            </div>
                            <Resizer
                                containerRef={this.resizerColumnRef}
                                minWidth={this.minResizerWidth}
                                maxWidth={this.props.resizerOptions?.maxWidth}
                                widthDashedBorder={true}/>
                        </>
                    );
                }

                return (
                    <div className={childStyles}>
                        {child}
                    </div>
                );
            });
        }

        return (
            <div className={classNames}>
                {children}
            </div>
        );
    }

    get cardStyle () {
        const cardStyle = joinClassNames(
            styles.cardPanel,
            [styles.internal, this.props.internal === true],
            [styles.contentAutoHeight, this.props.contentAutoHeight === true],
            [styles.noHeader, !this.drawHeader],
            [styles.wide, this.props.isWide === true]
        );

        return cardStyle;
    }

    get cardHeaderStyle () {
        const cardHeaderStyle = joinClassNames(
            styles.cardHeader,
            [styles.sticky, this.props.isSticky === true],
            [styles.themeDark, this.props.theme === 'dark'],
            [styles.themeLight, !this.props.theme || this.props.theme === 'default'],
            [styles.withLeftItems, Boolean(this.props.leftExtraItems)],
            [styles.withRightItems, Boolean(this.props.rightExtraItems)],
            [styles.isCollapsed, this.state.isCollapsed === true]
        );

        return cardHeaderStyle;
    }

    get renderHelper () {
        const helperContainerStyle = joinClassNames(
            styles.helperContainer,
            [styles.showHelp, this.state.isShowHelp]
        );

        return (
            <div className={helperContainerStyle}>
                <div className={styles.helperIcon} onClick={this.toggleHelp}>
                    <Icon name={'question-circle'} size={SIZE.EXTRA_LARGE}/>
                </div>

                {this.state.isShowHelp && (
                    <>
                        <div className={styles.helperTextContainer}>
                            {this.props.helperTitle && (<div className={styles.cardTitle}>{this.props.helperTitle}</div>)}

                            <div className={styles.helperText}>
                                {this.props.helperText}
                            </div>
                        </div>

                        <Button
                            leftIcon={'cross'}
                            isMinimal={true}
                            onClick={this.toggleHelp}
                        />
                    </>
                )}
            </div>
        );
    }

    private toggleHelp = () => {
        this.setState((prevState) => {
            return {
                isShowHelp: !prevState.isShowHelp
            };
        });
    }

    private setResizerDefaultWidth () {
        const el = this.resizerColumnRef?.current;

        if (el) {
            const width = this.getResizableWidth(el);

            el.style.setProperty('width', `${width}px`);

            this.minResizerWidth = width;
        }
    }

    override componentDidMount () {
        if (this.props.isCollapsed === undefined || this.props.isCollapsed === false) {
            this.setState({isCollapsed: false});
        }

        this.setResizerDefaultWidth();
    }

    override componentDidUpdate (prevProps: Readonly<ICardPanelProps>, prevState: Readonly<IState>, snapshot?: any): void {
        if (
            prevProps.isCollapsed !== undefined &&
            prevState.isCollapsed !== this.props.isCollapsed &&
            this.props.isCollapsed !== undefined
        ) {
            this.setState({isCollapsed: this.props.isCollapsed});
        }
    }

    handleCollapseClick = (e: React.SyntheticEvent<HTMLDivElement>) => {
        e.stopPropagation();
        this.setState((prevState) => ({
            isCollapsed: !prevState.isCollapsed
        }), () => {
            if (this.props.onToggleCollapse) {
                this.props.onToggleCollapse(this.state.isCollapsed);
            }
        });
    };

    private getResizableWidth (el: HTMLElement) {
        const resizableWidth = this.props.resizerOptions?.minWidth || this.DEFAULT_RESIZABLE_CONTENT_WIDTH;
        const width = Math.min(el.clientWidth, resizableWidth);

        return width;
    }

    override render () {
        const {title, leftExtraItems, isCollapsed, forwardRef, titleTooltip} = this.props;

        const leftExtraStyles = joinClassNames(
            styles.extraItemsContainer,
            styles.leftExtraItemsContainer
        );

        return (
            <div
                className={this.cardStyle}
                data-panel-id={this.props['data-panel-id']}
                data-qaid={this.props['data-qaid']}
                data-component-id={'CardPanel'}
                ref={forwardRef}
            >
                {this.props.mountOnExpand === true && this.state.isCollapsed === true ? null : this.renderContent}
                {this.drawHeader && (
                    <div
                        className={this.cardHeaderStyle}
                        onClick={isCollapsed !== undefined ? this.handleCollapseClick : undefined}
                    >
                        <div className={styles.leftItems}>
                            {leftExtraItems && (<div className={leftExtraStyles}>{leftExtraItems}</div>)}
                            {titleTooltip !== undefined ? (
                                <Tooltip overlay={titleTooltip} placement={PLACEMENT.BOTTOM}>
                                    <div className={styles.cardTitle}>{title}</div>
                                </Tooltip>
                            ) : (
                                <div className={styles.cardTitle}>{title}</div>
                            )}
                        </div>
                        <div className={styles.extraItemsContainer}>{this.rightItems}</div>
                    </div>
                )}
                {this.props.helperText !== undefined && this.renderHelper}
            </div>
        );
    }

}
