/**
 * 建立索引
 * @param   {[string]|[Object]}	 data         数据
 * @param	{string|[string]}    indexs       如果 data 为 [Object]，这里需要建立拼音索引 key
 * @param   {array}              dict         词典数据
 */
class Engine {
    constructor(data, indexs = [], dict = {}, prefix = '') {
        this.indexs = [];
        this.history = { keyword: '', indexs: [], data: [] };
        this.data = data;
        this.dict = dict;
        this.prefix = prefix;

        // 建立拼音关键词索引
        indexs = typeof indexs === 'string' ? [indexs] : indexs;
        for (const item of data) {
            let keywords = '';

            if (typeof item === 'string') {
                keywords = Engine.participle(item, dict, prefix);
            } else {
                for (const key of indexs) {
                    const words = item[key];
                    if (words) {
                        keywords += Engine.participle(words, dict, prefix);
                    }
                }
            }

            this.indexs.push(keywords.toLowerCase());
        }
    }

    /**
     * 查询
     * @param   {string}    keyword     拼音或者关键字
     * @return  {[string]|{Object}}
     */
    query(keyword) {

        keyword = keyword.replace(/\s/g, '').toLowerCase();

        if (keyword === '') {
            return [...this.data];
        }

        let indexs = this.indexs;
        let data = this.data;
        const history = this.history;
        const result = [];

        // 性能优化：在上一次搜索结果中查询
        if (history.data.length && keyword.indexOf(history.keyword) === 0) {
            indexs = history.indexs;
            data = history.data;
        }

        history.keyword = keyword;
        history.indexs = [];
        
        for (let index = 0; index < indexs.length; index ++) {
            if (indexs[index].indexOf(this.prefix+keyword) !== -1) {
                history.indexs.push(indexs[index]);
                result.push(data[index]);
            }
        }

        return result;
    }


    /**
     * 将内容进行分词
     * @param	{string}		  words        目标字符串
     * @param   {Object}          dict         字典
     * @return	{string}
     */
    static participle(words, dict, prefix='') {
        words = words.replace(/\s/g, '');
        let result = `${prefix}${words}`;
        const keywords = [[], []];

        for (const char of words) {
            const pinyin = dict[char];
            if (pinyin) {
                keywords[0].push(pinyin);
                if (words.length > 1) {
                    keywords[1].push(pinyin.map(p => p.charAt(0)));
                }
            }
        }

        for (const list of keywords) {
            let current = list.shift();

            while(list.length) {
                const array = [];
                const next = list.shift();
                for (const c of current) {
                    for (const n of next) {
                        array.push(c + n);
                    }
                }
                current = array;
            }

            if (current) {
                result += `\u0001${prefix}${current.join(`\u0001${prefix}`)}`;
            }
        }
        
        return result;
    }
};

module.exports = Engine;