/**
 * Resizer
 *
 * @author Brauer Ilya
 * @date 2021-06-29
 */
import * as React from 'react';
import {Divider, DIVIDER_TYPE, joinClassNames, safeInvoke} from '../..';
import * as styles from './resizer.m.scss';

interface IProps {
    containerRef: React.RefObject<HTMLElement>;

    onStartChangeWidth?: () => void;
    onStopChangeWidth?: () => void;

    widthBorder?: boolean;
    widthDashedBorder?: boolean;

    minWidth?: number;
    maxWidth?: number;
}

interface IDefaultProps {
    minWidth: number;
    maxWidth: number;
}

export class Resizer extends React.PureComponent<IProps> {

    static defaultProps: IDefaultProps = {
        minWidth: 160,
        maxWidth: 800
    };

    resizerRef = React.createRef<HTMLDivElement>();

    newWidth: number = 0;

    containerClientX: number = 0;

    get childRef (): React.RefObject<HTMLElement> {
        return this.props.containerRef;
    }

    handleMouseMove = (event: MouseEvent) => {
        event.preventDefault();

        const {minWidth, maxWidth} = this.props as IDefaultProps;

        this.newWidth = Math.abs(event.clientX - this.containerClientX - 5);

        if (this.childRef.current && this.newWidth >= minWidth && this.newWidth <= maxWidth) {
            this.childRef.current.style.setProperty('width', `${this.newWidth}px`);
        }
    };

    onMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
        event.preventDefault();

        if (this.childRef.current) {
            this.childRef.current.style.setProperty('transition', 'unset');
        }

        this.containerClientX = this.childRef.current?.getBoundingClientRect().left || 0;

        document.addEventListener('mousemove', this.handleMouseMove);
        document.addEventListener('mouseup', this.onMouseUp);

        safeInvoke(this.props.onStartChangeWidth);
    };

    onMouseUp = () => {
        if (this.childRef.current) {
            this.childRef.current.style.setProperty('transition', 'width 200ms');
        }

        document.removeEventListener('mousemove', this.handleMouseMove);
        document.removeEventListener('mouseup', this.onMouseUp);

        safeInvoke(this.props.onStopChangeWidth);
    };

    override render () {
        const {widthBorder, widthDashedBorder} = this.props;
        const withDivider = widthBorder === true || widthDashedBorder === true;
        const type = widthDashedBorder ? DIVIDER_TYPE.dashed : DIVIDER_TYPE.solid;

        const resizerStyles = joinClassNames(
            styles.resizeContainer,
            [styles.withDivider, withDivider]
        );

        return (
            <div
                className={resizerStyles}
                onMouseDown={this.onMouseDown}
                ref={this.resizerRef}
            >
                <div/>
                {withDivider && (
                    <Divider
                        offset={0}
                        orientation={'vertical'}
                        type={type}
                    />
                )}
                <div/>
            </div>
        );
    }
}
