import { observable } from 'mobx';
import { observer } from 'mobx-react';
import { Component, createRef, CSSProperties, HTMLAttributes, ReactNode } from 'react';

export interface TextTruncateProps extends HTMLAttributes<HTMLDivElement> {
    rows?: number;
    expandText?: ReactNode;
    collapseText?: ReactNode;
}

@observer
export class TextTruncate extends Component<TextTruncateProps> {
    static displayName = 'TextTruncate';

    @observable
    accessor expanded = false;

    @observable
    accessor overflowed = false;

    contentRef = createRef<HTMLParagraphElement>();

    componentDidMount() {
        this.checkOverflow();
        window.addEventListener('resize', this.checkOverflow);
    }

    componentDidUpdate({ rows, children }: TextTruncateProps) {
        if (!this.expanded && (children !== this.props.children || rows !== this.props.rows))
            this.checkOverflow();
    }

    componentWillUnmount() {
        window.removeEventListener('resize', this.checkOverflow);
    }

    checkOverflow = () => {
        const { current } = this.contentRef;

        if (current) this.overflowed = current.scrollHeight > current.clientHeight;
    };

    toggle = () => {
        this.expanded = !this.expanded;

        if (!this.expanded) requestAnimationFrame(this.checkOverflow);
    };

    render() {
        const { children, rows = 3, expandText = '⏬', collapseText = '⏫', ...props } = this.props;
        const { expanded, overflowed } = this;
        const style: CSSProperties = {
            overflow: 'hidden',
            display: '-webkit-box',
            WebkitBoxOrient: 'vertical',
            WebkitLineClamp: rows
        };
        return (
            <div {...props}>
                <p ref={this.contentRef} style={expanded ? undefined : style}>
                    {children}
                </p>
                {(overflowed || expanded) && (
                    <button
                        type="button"
                        className="bg-transparent border-0 p-0"
                        aria-expanded={expanded}
                        onClick={this.toggle}
                    >
                        {expanded ? collapseText : expandText}
                    </button>
                )}
            </div>
        );
    }
}
