package com.yihu.hos.crawler.storage;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.UpdateOptions;
import com.yihu.hos.common.mongo.MongoDB;
import com.yihu.hos.core.datatype.DateUtil;
import com.yihu.hos.core.encode.Base64;
import com.yihu.hos.core.file.FileUtil;
import com.yihu.hos.crawler.format.AdapterScheme;
import com.yihu.hos.crawler.format.DocumentTransformer;
import com.yihu.hos.crawler.format.IDataTransformer;
import com.yihu.hos.crawler.model.patient.Patient;
import com.yihu.hos.crawler.service.EsbHttp;
import com.yihu.hos.crawler.service.PatientCDAIndex;
import org.bson.Document;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Projections.excludeId;

//import com.yihu.common.util.log.DebugLogger;

/**
 * Created by Administrator on 2015/10/15.
 */
public class DocumentStorage extends MongodbStorage {
        public static final String KEY_CODE = "catalog";

    public DocumentStorage(AdapterScheme adapterScheme, String dbName) {
        super(adapterScheme, dbName);
    }


    @Override
    public boolean save(IDataTransformer dataTransformer) {
        DocumentTransformer documentTransformer = (DocumentTransformer) dataTransformer;
        JsonNode jsonObject = documentTransformer.getJsonObject();

        if (jsonObject != null) {
            String dataSetCode = jsonObject.get(getKey()).asText();
            String documentId = jsonObject.path(getKey()).asText();
            System.out.println(documentId);
            String patientId = jsonObject.get(PATIENT_ID).asText();
            String eventNo = jsonObject.get(EVENT_NO).asText();

            try {
                MongoCollection<Document> collection = MongoDB.db(dbName).getCollection(dataSetCode);
                createIndex(collection);    //创建索引

                Document filter = new Document();
                filter.append(PATIENT_ID, patientId);
                filter.append(EVENT_NO, eventNo);
                collection.deleteMany(filter);
                UpdateOptions updateOptions = new UpdateOptions();
                updateOptions.upsert(true);
                collection.replaceOne(filter, Document.parse(jsonObject.toString()), updateOptions);


                String url = createUrl(dataSetCode, patientId, eventNo);

                Date expiryDate = DateUtil.setDateTime(new Date(), getExpireDays().intValue());
                SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DEFAULT_YMDHMSDATE_FORMAT);
                String date = sdf.format(expiryDate);

                Document updateDoc = new Document(CREATE_AT, new Date());
                updateDoc.put("resource.url", url);
                updateDoc.put("resource.expiry_date", date);
                collection.updateMany(filter, new Document("$set", updateDoc));
            } catch (Exception e) {
                //DebugLogger.fatal("保存病人档案信息至MongoDB异常:", e);
                return false;
            }

            return true;
        }

        return false;
    }


    /**
     * @param patient
     * @return
     * @modify 将档案生成到到data目录
     */
    @Override
    public boolean toFile(Patient patient) {
        boolean result = true;
        PatientCDAIndex patientCDAIndex = new PatientCDAIndex(patient);
        ObjectMapper mapper = new ObjectMapper();
        ArrayNode arrayNode=mapper.createArrayNode();
        ObjectNode resultNode=mapper.createObjectNode();
        try {
            for (String name : MongoDB.db(dbName).listCollectionNames()) {
                MongoCollection<Document> collection = MongoDB.db(dbName).getCollection(name);
                FindIterable<Document> documents = collection.find(and(eq("patient_id", patient.getPatientId()), eq(EVENT_NO, patient.getEventNo()))).projection(excludeId());

                try (MongoCursor<Document> cursor = documents.iterator()) {
                    while (cursor.hasNext()) {
                        try {
                            String document = cursor.next().toJson();
                            ObjectNode rootNode = mapper.readValue(document, ObjectNode.class);
                            JsonNode jsonNode = rootNode.get("data");
                            boolean array = jsonNode.isArray();
                            if (!array) {
                                continue;
                            }
                            arrayNode=genunStructureData(jsonNode,patientCDAIndex);
                        } catch (IOException e) {
                            e.printStackTrace();
                            //DebugLogger.fatal("存储临时文件失败.");
                            result = false;
                        }
                    }
                } catch (Exception e) {
                    //DebugLogger.fatal("", e);
                    result = false;
                }
            }
            String innerVersion =  EsbHttp.getRemoteVersion(patient.getOrgCode());
            for (int i = 0; i != arrayNode.size(); ++i) {
                JsonNode keyWordsNode = arrayNode.get(i).path("key_words");
                ObjectNode newNode=mapper.createObjectNode();
                JsonNode jsonNode= transformKeyWords(keyWordsNode, newNode);
                ((ObjectNode) arrayNode.get(i)).set("key_words", jsonNode);
            }


            resultNode.set("data", arrayNode);
            resultNode.put("patient_id", patient.getPatientId());
            resultNode.put("event_no",patient.getEventNo());
            resultNode.put("org_code",patient.getOrgCode());
            resultNode.put("event_time",patient.getReferenceTime());
            resultNode.put("inner_version",innerVersion);

            String indexPath = patientCDAIndex.getDataDirectory()+"/"+"meta.json";
            boolean writeFile = FileUtil.writeFile(indexPath, mapper.writeValueAsString(resultNode), "UTF-8");

        } catch (Exception e) {
            //DebugLogger.fatal("", e);
            result = false;
        }
        return result;
    }

    @Override
    public String getDataSet(Patient patient, String dataSetCode) {
        return null;
    }

    @Override
    public String getKey(){
        return KEY_CODE;
    }


    /**
     * 生成非结构化 meta.json文件数据
     * @param jsonNode
     * @param patientCDAIndex
     * @return
     * @throws IOException
     */
    public ArrayNode genunStructureData(JsonNode jsonNode,PatientCDAIndex patientCDAIndex) throws IOException {
        ObjectMapper mapper=new ObjectMapper();
        ArrayNode arrayNode=mapper.createArrayNode();
        for (int i = 0; i != jsonNode.size(); ++i) {
            JsonNode documentNode = jsonNode.get(i);
            JsonNode contentNode=documentNode.path("content");
            if (contentNode.isArray()){
                for (int j = 0; j< contentNode.size(); j++) {
                    JsonNode fileArr = contentNode.get(j);
//                    String mimeType = fileArr.path("mime_type").asText();//文件类型
                    String names = fileArr.path("name").asText();
                    String fileType=names.substring(names.lastIndexOf("."));//文件后缀
                    JsonNode file=fileArr.path("file_content");//文件内容
                    Iterator<String> fileNames = file.fieldNames();
                    StringBuilder stringBuilder=new StringBuilder();
                    while (fileNames.hasNext()){
                        String key=fileNames.next();
                        String content =file.path(key).asText();
                        String filePath = patientCDAIndex.createDataIndex(dbName, fileType);
                        String fileName = filePath.substring(filePath.lastIndexOf("/")+1);

                        byte[]  fileContent = Base64.decode(content);
                        boolean writeFile = FileUtil.writeFile(filePath, fileContent, "UTF-8");
                        if (!writeFile) {
                            //DebugLogger.fatal("存储临时文件失败.");
                        } else {
                            stringBuilder.append(fileName).append(",");
                        }
                    }
                    if (file.isObject()) {
                        ((ObjectNode) fileArr).put("name", stringBuilder.toString());
                        ((ObjectNode) fileArr).remove("file_content");
                    }
                }
            }
            arrayNode.add(documentNode);
        }
        return arrayNode;
    }

    /**
     * 将key_words中key中包含的“-”转换成“."
     * @param keyWordsNode
     * @param newObjectNode
     * @return
     */
    public ObjectNode transformKeyWords(JsonNode keyWordsNode, ObjectNode newObjectNode){
        Iterator<String> iterator = keyWordsNode.fieldNames();
        while (iterator.hasNext()){
            String key=iterator.next();
            String value =keyWordsNode.path(key).asText();
            String newKey=key.replaceAll("-",".");
            newObjectNode.put(newKey,value);
        }
        return newObjectNode;
    }

}
