package org.algorithm.core.neural.dataset;

import org.algorithm.util.TextFileReader;
import org.diagbot.pub.utils.PropertiesUtil;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;

/**
 * 门诊诊断推送用数据集
 *
 * @Author: bijl
 * @Date: 2018年7月26日-上午10:19:43
 * @Description:
 */
public class NNDataSetImpl extends NNDataSet {


    public NNDataSetImpl(String modelAndVersion) {
        super(modelAndVersion);
    }

    @Override
    public float[] toFeatureVector(Map<String, Map<String, String>> inputs) {

        // 新添加的操作
        this.reSplitWord(inputs);  // 再分词
        this.storeFeatureNames(inputs);  // 保存特征名称

        float[] featureVector = new float[this.NUM_FEATURE];

        Iterator<Entry<String, Map<String, String>>> entries = inputs.entrySet().iterator();

        String featureName = "";
        Integer position = -1;
        Integer negative = 0;
        float positive_value = 1.0f;
        float negative_value = -1.0f;
        Map<String, String> featureValues = null;

        /**
         * 数据方案设计
         */
        while (entries.hasNext()) {


            Entry<String, Map<String, String>> entry = entries.next();
            featureName = entry.getKey();
            featureValues = entry.getValue();
            position = this.FEATURE_DICT.get(featureName);
            negative = NEGATIVE_DICT.get(featureValues.get("negative"));

            if (position != null)
                if (negative == 1)
                    featureVector[position] = positive_value;
                else if (negative == -1)
                    featureVector[position] = negative_value;
                else
                    System.out.println("New Nagetive! This may lead to an error.");

        }

        return featureVector;
    }

    @Override
    public int[] toCharIds(Map<String, Map<String, String>> inputs) {
        String sentence = inputs.get("sentence").get("sentence");
        int max_len = this.getMAX_LEN();
        int[] ids = new int[max_len];
        char ch = '1';
        Integer id = null;
        for (int i = 0; i < sentence.length() && i < max_len; i++) {  // 不超过最大长度
            ch = sentence.charAt(i);
            id = this.CHAR2ID_DICT.get(String.valueOf(ch));
            if (id == null) {
                id = this.CHAR2ID_DICT.get("<UNC>");
            }
            ids[i] = id;
        }
        for (int i = sentence.length(); i < max_len; i++)  // padding
            ids[i] = this.CHAR2ID_DICT.get("<PAD>");

        return ids;
    }

    @Override
    public int[] toPosIds(Map<String, Map<String, String>> inputs) {
        int max_len = this.getMAX_LEN();
        String sentence = inputs.get("sentence").get("sentence");
        int[] pos_ids = new int[max_len];
        for (int j=0; j<max_len; j++)
            pos_ids[j] = max_len - 1;  // 位置的padding

        // 绝对位置编码
        for (int i = 0 ; i < (sentence.length() < max_len ? sentence.length() : max_len); i++)
            pos_ids[i] = i;

        return pos_ids;
    }

    @Override
    public void readDict(String modelAndVersion) {

        PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
        String model_version = prop.getProperty(modelAndVersion);

        String filePath = prop.getProperty("basicPath");  // 基本目录
        filePath = filePath.substring(0, filePath.indexOf("model_version_replacement"));

        filePath = filePath + "dictionaries.bin";  // 字典文件位置

        List<String> lines = TextFileReader.readLines(filePath);

        boolean firstLine = true;

        String[] temp = null;
        for (String line : lines) {
            if (firstLine) {  // 去除第一行
                firstLine = false;
                continue;
            }

            temp = line.split("\\|");

            if (temp[3].equals(model_version)) {
                int type_id = Integer.parseInt(temp[2]);
                int _index = Integer.parseInt(temp[1]);
                String _name = temp[0];

                if (type_id == 1)
                    this.FEATURE_DICT.put(_name, _index);
                else if (type_id == 2)
                    this.LABEL_DICT.put(_name, _index);
                else if (type_id == 8)
                    this.NEGATIVE_DICT.put(_name, _index);
            }

        }

//        System.out.println("feature size:" + this.FEATURE_DICT.size());

    }

    @Override
    public void readChar2IdDict(String modelAndVersion) {

        // 获取文件目录
        PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
        String filePath = prop.getProperty("basicPath");  // 基本目录
        filePath = filePath.substring(0, filePath.indexOf("model_version_replacement"));

        filePath = filePath + "char2id.bin";  // 字典文件位置

        // 读取以json字符串保存的数据
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(filePath));  // 读取原始json文件
            String line = null;
            String[] pair = null;
            while ((line = br.readLine()) != null) {
                line = line.trim();
                if (line.indexOf("_|_") > -1){
                    pair = line.split("_\\|_");
                    this.CHAR2ID_DICT.put(pair[0], Integer.parseInt(pair[1]));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 再分词：
     * 基本操作：
     * 如果再分词表中有某一词项，则移除它，并添加该此项对应的细分词项
     *
     * @param inputs 输入
     */
    public void reSplitWord(Map<String, Map<String, String>> inputs) {
        Iterator<Entry<String, Map<String, String>>> entries = inputs.entrySet().iterator();

        String featureName = "";
        String[] splitWords = null;
        Map<String, String> featureValues = null;
        Entry<String, Map<String, String>> entry;

        Map<String, Map<String, String>> tempHashMap = new HashMap<>();  // 用于暂存key, value

        while (entries.hasNext()) {
            entry = entries.next();
            featureName = entry.getKey();
            if (this.FEATURE_DICT.get(featureName) == null  // 特征字典中没有然后再分词
                    && this.RE_SPLIT_WORD_DICT.get(featureName) != null) {
                entries.remove();  // 移除该词项
                splitWords = this.RE_SPLIT_WORD_DICT.get(featureName).split(",");
                for (String word : splitWords) {  // 添加细分词项
                    featureValues = new HashMap<>();
                    featureValues.put("negative", "有"); // 设置为阳性词
                    tempHashMap.put(word, featureValues);
                }

            }
        }

        inputs.putAll(tempHashMap);
    }

    @Override
    public void readReSplitWordDict() {
        PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
        String filePath = prop.getProperty("basicPath");  // 基本目录
        filePath = filePath.substring(0, filePath.indexOf("model_version_replacement"));

        filePath = filePath + "re_split_word.bin";  // 字典文件位置

        List<String> lines = TextFileReader.readLines(filePath);

        boolean firstLine = true;

        String[] temp = null;
        Map<String, String> feature_map = null;
        for (String line : lines) {
            if (firstLine) {  // 去除第一行
                firstLine = false;
                continue;
            }

            temp = line.split("\\|");

            this.RE_SPLIT_WORD_DICT.put(temp[0], temp[1]);

        }

//        System.out.println("再分词，词条数:" + this.RE_SPLIT_WORD_DICT.size());

    }

    @Override
    public void readFilterDiagnosisDict() {
        PropertiesUtil prop = new PropertiesUtil("/algorithm.properties");
        String filePath = prop.getProperty("basicPath");  // 基本目录
        filePath = filePath.substring(0, filePath.indexOf("model_version_replacement"));

        filePath = filePath + "filter_diagnoses.bin";  // 字典文件位置

        List<String> lines = TextFileReader.readLines(filePath);

        boolean firstLine = true;

        String[] temp = null;
        String[] diagnoses = null;
        Map<String, Integer> diagnosis_map = null;
        for (String line : lines) {
            if (firstLine) {  // 去除第一行
                firstLine = false;
                continue;
            }

            temp = line.split("\\|");
            diagnoses = temp[1].split("_");
            diagnosis_map = new HashMap<>();
            for (String diagnosis: diagnoses)
                diagnosis_map.put(diagnosis, 1);
            this.RELATED_DIAGNOSIS_DICT.put(temp[0], diagnosis_map);
        }

//        System.out.println("疾病过滤字典大小:" + this.RELATED_DIAGNOSIS_DICT.size());
    }


}
