import * as React from 'react';
import VisibilitySensor from 'react-visibility-sensor';
import { highlightNode } from '../util/dom';
import { LinkOrSpan } from './LinkOrSpan';
/**
 * A simple component for displaying lines of text, with optional
 * highlighted ranges (not syntax highlighting, only e.g. query match
 * highlighting).
 */
export class DecoratedTextLines extends React.PureComponent {
    constructor(props) {
        super(props);
        this.tableContainerElement = null;
        this.onChangeVisibility = (isVisible) => {
            this.setState({ visible: true });
        };
        this.setTableContainerElement = (ref) => {
            this.tableContainerElement = ref;
        };
        this.state = Object.assign({}, this.getStateForProps(props), { visible: false });
    }
    componentDidMount() {
        this.updateHighlights();
    }
    componentWillReceiveProps(nextProps) {
        if (this.props.value !== nextProps.value ||
            this.props.highlights !== nextProps.highlights ||
            this.props.lineClasses !== nextProps.lineClasses) {
            this.setState(this.getStateForProps(nextProps));
        }
    }
    componentDidUpdate(prevProps, prevState) {
        this.updateHighlights();
    }
    updateHighlights() {
        if (this.state.visible && this.tableContainerElement) {
            const rows = this.tableContainerElement.querySelectorAll('table tr');
            for (const [i, row] of rows.entries()) {
                const elem = row.firstChild;
                const data = this.state.lines[i];
                if (data.highlights && data.highlights.length) {
                    // TODO(sqs): only supports 1 highlight per line
                    const highlight = data.highlights[0];
                    highlightNode(elem, highlight.character, highlight.length);
                }
            }
        }
    }
    getStateForProps(props) {
        const lineValues = typeof props.value === 'string' ? props.value.split('\n') : props.value;
        const lines = lineValues.map(line => ({ value: line }));
        if (props.highlights) {
            for (const highlight of props.highlights) {
                const line = lines[highlight.line - 1];
                if (!line.highlights) {
                    line.highlights = [];
                }
                line.highlights.push(highlight);
            }
        }
        if (props.lineClasses) {
            for (const { line: lineNumber, className, url } of props.lineClasses) {
                const line = lines[lineNumber - 1];
                if (!line.classNames) {
                    line.classNames = [];
                }
                line.classNames.push(className);
                if (url) {
                    line.url = url;
                }
            }
        }
        return { lines };
    }
    render() {
        return (React.createElement(VisibilitySensor, { onChange: this.onChangeVisibility, partialVisibility: true },
            React.createElement("code", { className: `decorated-text-lines code-excerpt ${this.props.className || ''}` },
                React.createElement("table", { ref: this.setTableContainerElement },
                    React.createElement("tbody", null, this.state.lines.map((line, i) => (React.createElement("tr", { key: i, className: line.classNames ? line.classNames.join(' ') : undefined },
                        React.createElement("td", { className: "code", onMouseDown: this.props.onMouseDown },
                            React.createElement(LinkOrSpan, { to: line.url }, line.value))))))))));
    }
}
//# sourceMappingURL=DecoratedTextLines.js.map