/**
 * Render Cell in Tree Node
 *
 * @author Brauer Ilya
 * @date 2020-10-29
 */

import {AbstractModel} from '@unidata/core';
import * as React from 'react';
import {ITreeColumn, ITreeNode} from './TreeType';
import {Button, Icon, Input, PLACEMENT, POPOVER_THEME, safeInvoke, SIZE, Tooltip} from '../../index';
import * as styles from './tree.m.scss';
import {ConditionFunc} from './Node';

interface IProps<T> {
    node: ITreeNode<T>;
    column: ITreeColumn<T>;

    isEdited?: boolean;
    isEditable?: boolean | ConditionFunc<T>;

    onEdit?: (node: ITreeNode<T>, newValue: string, cellId: string) => void;
}

interface IState {
    isEditable: boolean;
    editableCell: string;
    isCellHovered: boolean;
    showTooltip: boolean;
}

const tooltipModify = [
    {
        name: 'offset',
        options: {
            offset: [-4, -19]
        }
    }
];

export class Cell<T> extends React.PureComponent<IProps<T>, IState> {
    titleRef = React.createRef<HTMLDivElement>();

    override state: IState = {
        isEditable: false,
        editableCell: '',
        isCellHovered: false,
        showTooltip: false
    };

    override componentDidMount () {
        this.calcTooltip();
    }

    calcTooltip () {
        const titleElement = this.titleRef.current;

        if (titleElement !== null && titleElement.scrollWidth > titleElement.offsetWidth) {
            this.setState({showTooltip: true});
        }
    }

    setEditable = (e: React.SyntheticEvent<HTMLButtonElement>) => {
        e.stopPropagation();

        this.setState({
            isEditable: true,
            editableCell: this.props.column.name
        });
    };

    renderInput = (value: string, node: ITreeNode<T>, column: ITreeColumn<T>) => {
        const me = this;

        return (
            <Input
                autoFocus={true}
                defaultValue={value}
                size={SIZE.SMALL}
                onBlur={function (event) {
                    safeInvoke(me.props.onEdit, node, event.currentTarget.value, column.name);
                    me.setState({isEditable: false, editableCell: ''});
                }}
                onKeyDown={function (event) {
                    switch (event.keyCode) {
                        case 13:
                            safeInvoke(me.props.onEdit, node, event.currentTarget.value, column.name);
                            me.setState({isEditable: false, editableCell: ''});
                            break;
                        case 27:
                            event.stopPropagation();
                            me.setState({isEditable: false, editableCell: ''});
                            break;
                    }
                }}
            />
        );
    };

    onMouseEnter = () => {
        this.setState({isCellHovered: true});
    };

    onMouseLeave = () => {
        this.setState({isCellHovered: false});
    };

    override render () {
        const {node, column} = this.props;
        const clsName = styles.column;

        const isEditable = typeof this.props.isEditable === 'function' ?
            this.props.isEditable(node, column) :
            this.props.isEditable;

        let value = node.row instanceof AbstractModel ? node.row.getField(column.name)?.getValue() : (node.row as any)[column.name];

        if (column.renderer) {
            value = column.renderer(node);
        }

        return (
            <div
                className={clsName}
                onMouseEnter={this.onMouseEnter}
                onMouseLeave={this.onMouseLeave}
            >
                {this.props.children}
                {(this.state.isEditable && this.state.editableCell === column.name) || this.props.isEdited === true ? (
                    this.renderInput(value, node, column)
                ) : (
                    <>
                        {node.icon && <span className={styles.iconContainer}><Icon name={node.icon} /></span>}
                        {this.state.showTooltip === false ? (
                            <span className={styles.rowContainer} ref={this.titleRef}>{value}</span>
                        ) : (
                            <Tooltip
                                overlay={(<div className={styles.itemOverlay}>{value}</div>)}
                                placement={PLACEMENT.BOTTOM_START}
                                theme={POPOVER_THEME.LIGHT}
                                hasArrow={false}
                                hasPaddings={false}
                                mouseEnterDelay={600}
                                modifiers={tooltipModify}
                            >
                                <span className={styles.rowContainer}>
                                    {value}
                                </span>
                            </Tooltip>
                        )}
                        {isEditable === true && this.state.isCellHovered && (
                            <Button
                                leftIcon={'pencil-line'}
                                isMinimal={true}
                                size={SIZE.SMALL}
                                onClick={this.setEditable}
                            />
                        )}
                    </>
                )}
            </div>
        );
    }
}
