import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import {htmlTagRegEx} from '../../utils/constants';

function highlight(matchedText, listHighlightType) {
    switch (listHighlightType) {
        case HIGHLIGHT_TYPE.BACKGROUND:
            return `<span class="rc-highlight">${matchedText}</span>`;
        case HIGHLIGHT_TYPE.BOLD:
            return `<strong>${matchedText}</strong>`;
        default:
            return matchedText;
    }
}

export const HIGHLIGHT_TYPE = {
    BACKGROUND: 'BACKGROUND',
    BOLD: 'BOLD'
};

export const NO_HIGHLIGHT_REGEX = /<nhl>.*?<\/nhl>/g;

export class Highlighter extends React.Component<any> {
    static propTypes = {
        children: PropTypes.node,
        listHighlightType: PropTypes.oneOf([HIGHLIGHT_TYPE.BACKGROUND, HIGHLIGHT_TYPE.BOLD]),
        highlightRegexp: PropTypes.object,
        filterRegexp: PropTypes.object,
        highlight: PropTypes.func,
        title: PropTypes.string
    };

    static defaultProps = {
        children: null,
        listHighlightType: HIGHLIGHT_TYPE.BOLD,
        highlightRegexp: null,
        filterRegexp: null,
        title: null,
        highlight
    };

    static arraysToString(arr1, arr2) {
        return _.zipWith(arr1, arr2, (item1, item2) => {
            return ((item1 || '') as any) + (item2 || '');
        }).join('');
    }

    emphazis(part) {
        return part ? this.props.highlight(_.escape(part), this.props.listHighlightType) : part;
    }

    shouldProceedWithHighlight() {
        let isFiltred = true;
        const {children, highlightRegexp, filterRegexp} = this.props;
        const childrenString = String(children).replace(htmlTagRegEx, '');

        if (filterRegexp) {
            filterRegexp.lastIndex = 0;
            isFiltred = filterRegexp.test(childrenString);
        }

        return highlightRegexp && isFiltred;
    }

    getHighlightedChild() {
        const {children} = this.props;
        const childrenString = String(children);

        let string = '';

        if (this.shouldProceedWithHighlight()) {
            NO_HIGHLIGHT_REGEX.lastIndex = 0;
            let wordsToHL = childrenString.split(NO_HIGHLIGHT_REGEX);
            let wordsNotToHL = childrenString.match(NO_HIGHLIGHT_REGEX);
            wordsToHL = wordsToHL.map(wordToHL => this.highlightPart(wordToHL));
            string = Highlighter.arraysToString(wordsToHL, wordsNotToHL);
        }

        return string || childrenString;
    }

    highlightPart(text) {
        const {highlightRegexp} = this.props;
        let words = text.split(htmlTagRegEx);
        let tags = text.match(htmlTagRegEx);

        words = words.map(word => {
            return _.unescape(word).replace(highlightRegexp, matchedText => {
                return this.emphazis(matchedText);
            });
        });

        return Highlighter.arraysToString(words, tags);
    }

    render() {
        const {title} = this.props;
        const highlightedText = this.getHighlightedChild();
        return <span title={title} dangerouslySetInnerHTML={{__html: highlightedText}} />;
    }
}
