package com.wx.application.nebula.graph.service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wx.application.core.entity.OntologyConcept;
import com.wx.application.core.entity.OntologyField;
import com.wx.application.core.entity.OntologyRelation;
import com.wx.application.core.service.OntologyConceptService;
import com.wx.application.core.service.OntologyFieldService;
import com.wx.application.core.service.OntologyRelationService;
import com.wx.application.nebula.graph.base.Generators;
import com.wx.application.nebula.graph.bean.ModelEdgeLine;
import com.wx.application.nebula.graph.bean.ModelVertex;
import com.wx.application.nebula.graph.bean.NebulaField;
import com.wx.application.nebula.graph.enums.DataType;
import com.wx.application.util.InputStreamCache;

import cn.hutool.json.JSONObject;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.sax.handler.RowHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * 本体模型导入
 */
@Slf4j
@Service
public class ImportModelService {
	
	@Autowired
	NebulaModelService nebulaModelService;
	
	@Autowired
	OntologyConceptService ontologyConceptService;
	
	@Autowired
	OntologyFieldService ontologyFieldService;
	
	@Autowired
	OntologyRelationService ontologyRelationService;
	
	/**
     * 导入数据解析excel
     */
    public JSONObject analysisExcel(Long ontologyId, InputStream in) {
    	
    	InputStreamCache inCache = new InputStreamCache(in);
    	
    	List<ModelVertex> mxs = new ArrayList<>();
    	List<ModelEdgeLine> mes = new ArrayList<>();
    	
    	List<OntologyConcept> ontologyConcepts = new ArrayList<>();
    	Map<String,OntologyField> ontologyFields = new HashMap<>();
    	Map<String,OntologyRelation> ontologyRelations = new HashMap<>();
    	
    	
    	ExcelReader reader = ExcelUtil.getReader(inCache.getInputStream());
    	List<String> sns = reader.getSheetNames();
    	for(int i=0;i<sns.size();i++) {
    		switch (sns.get(i)) {
			case "本体":
				ExcelUtil.readBySax(inCache.getInputStream(), i, analysisTag(mxs,ontologyConcepts,ontologyId));
				break;
			case "关系":
				ExcelUtil.readBySax(inCache.getInputStream(), i, analysisEdge(mes,ontologyRelations,ontologyId));
				break;
			case "本体属性":
				ExcelUtil.readBySax(inCache.getInputStream(), i, analysisTagField(mxs,ontologyFields,ontologyId));
				break;
			case "关系属性":
				ExcelUtil.readBySax(inCache.getInputStream(), i, analysisEdgeField(mes));
				break;
			default:
				break;
			}
    	}
    	reader.close();
    	inCache.destroyCache();
    	
    	ontologyConceptService.insertBatchByXml(ontologyConcepts);
    	ontologyFieldService.insertBatchByXml(new ArrayList<>(ontologyFields.values()));
    	ontologyRelationService.insertBatchByXml(new ArrayList<>(ontologyRelations.values()));
    	
    	/**
    	 * 执行导入
    	 */
    	nebulaModelService.insertBatchModelVertex(mxs);
    	
    	nebulaModelService.insertBatchModelEdge(mes);
    	
    	
    	JSONObject result = new JSONObject();
    	result.set("gncount", ontologyConcepts.size());
    	result.set("gxscount", ontologyRelations.size());
    	result.set("zsxcount", ontologyFields.size());
    	
    	return result;
    }
	
    
    private RowHandler analysisTag(List<ModelVertex> mxs, 
    		List<OntologyConcept> ontologyConcepts, Long ontologyId) {
    	
    	return new RowHandler() {
            @Override
            public void handle(int sheetIndex, long rowIndex, List<Object> rowlist) {
            	if(rowIndex > 0) {
            		
            		Object index = rowlist.get(0);
            		if(index == null || StringUtils.isBlank(index.toString())) {
            			return;
            		}
            		
            		ModelVertex mx = new ModelVertex();
            		mx.setOntologyId(ontologyId);
            		
            		/**
            		 * 标签label	唯一id	名称	父id

            		 */
            		String vid = rowlist.get(1) != null?rowlist.get(1).toString():null;
            		String label = rowlist.get(2) != null?rowlist.get(2).toString():null;
            		String parentId = rowlist.get(3) != null?rowlist.get(3).toString():null;
            		
            		if(StringUtils.isBlank(vid)) {
            			return;
            		}
            		
            		if(StringUtils.isBlank(label)) {
            			return;
            		}

            		mx.setTagName(Generators.tagname(label));
            		mx.setLabel(label);
            		
            		/**
            		 * 设置id
            		 */
            		mx.setVid(Generators.ontologyVid(ontologyId, vid));
            		
            		/**
            		 * 执行mysql的对象封装
            		 */
            		OntologyConcept ct = new OntologyConcept();
            		ct.setOntologyId(ontologyId);
            		ct.setLabel(label);
            		ct.setOwnId(Generators.ontologyVid(ontologyId, vid));
            		ct.setParentId(Generators.ontologyVid(ontologyId, parentId));
            		
            		ontologyConcepts.add(ct);
            		
            		mxs.add(mx);
            	}
            }
    	};
    }
    
    private RowHandler analysisTagField(List<ModelVertex> mxs, 
    		Map<String,OntologyField> ontologyFields, Long ontologyId) {
    	
    	Map<String, ModelVertex> mvMap = mxs.stream().collect(
                Collectors.toMap(ModelVertex::getVid, a -> a, (k1, k2) -> k1));
    	
    	return new RowHandler() {
            @Override
            public void handle(int sheetIndex, long rowIndex, List<Object> rowlist) {
            	if(rowIndex > 1) {
            		
            		Object index = rowlist.get(0);
            		if(index == null || StringUtils.isBlank(index.toString())) {
            			return;
            		}
            		
            		String vid_ = rowlist.get(1) != null?rowlist.get(1).toString():null;
            		String strfield = rowlist.get(3) != null?rowlist.get(3).toString():null;
            		String strtype = rowlist.get(4) != null?rowlist.get(4).toString():null;
            		String comment = rowlist.get(5) != null?rowlist.get(5).toString():null;
            		
            		if(StringUtils.isBlank(strfield) && StringUtils.isBlank(comment)) {
            			return;
            		}
            		
            		if(StringUtils.isBlank(strfield)) {
            			strfield = Generators.fieldname(comment);
            		}
            		
            		if(StringUtils.isBlank(strtype)) {
            			strtype = "STRING";
            		}
            		DataType type = DataType.valueOf(strtype.toUpperCase());
            		
            		/**
            		 * 添加mysql对象
            		 */
            		OntologyField ofd = new OntologyField();
            		ofd.setOntologyId(ontologyId);
            		ofd.setField(strfield);
            		ofd.setType(type);
            		ofd.setComment(comment);
            		ontologyFields.put(strfield, ofd);
            		
            		String vid = Generators.ontologyVid(ontologyId, vid_);
            		
            		if(StringUtils.isBlank(vid) || !mvMap.containsKey(vid)) {
            			return;
            		}
            		
            		ModelVertex modelVertex = mvMap.get(vid);
            		if(modelVertex == null) {
            			return;
            		}
            		
            		if(modelVertex.getFields() == null) {
            			modelVertex.setFields(new ArrayList<>());
            		}
            		
            		NebulaField field = new NebulaField();
            		field.setType(type);
            		field.setComment(comment);
            		field.setField(strfield);
            		modelVertex.getFields().add(field);
            	}
            }
    	};
    }
    
    
    private RowHandler analysisEdgeField(List<ModelEdgeLine> mes) {
    	
    	Map<String, ModelEdgeLine> mvMap = mes.stream().collect(
                Collectors.toMap(ModelEdgeLine::getLabel, a -> a, (k1, k2) -> k1));
    	
    	return new RowHandler() {
            @Override
            public void handle(int sheetIndex, long rowIndex, List<Object> rowlist) {
            	if(rowIndex > 0) {
            		
            		Object index = rowlist.get(0);
            		if(index == null || StringUtils.isBlank(index.toString())) {
            			return;
            		}
            		
            		String label = rowlist.get(1) != null?rowlist.get(1).toString():null;
            		String strfield = rowlist.get(2) != null?rowlist.get(2).toString():null;
            		String strtype = rowlist.get(3) != null?rowlist.get(3).toString():null;
            		String comment = rowlist.get(4) != null?rowlist.get(4).toString():null;
            		
            		if(StringUtils.isBlank(label) || !mvMap.containsKey(label)) {
            			return;
            		}
            		
            		if(StringUtils.isBlank(strfield) && StringUtils.isBlank(comment)) {
            			return;
            		}
            		
            		ModelEdgeLine modelEdgeLine = mvMap.get(label);
            		if(modelEdgeLine == null) {
            			return;
            		}
            		
            		
            		if(modelEdgeLine.getFields() == null) {
            			modelEdgeLine.setFields(new ArrayList<>());
            		}
            		
            		
            		NebulaField field = new NebulaField();
            		
            		if(StringUtils.isBlank(strtype)) {
            			strtype = "STRING";
            		}
            		DataType type = DataType.valueOf(strtype.toUpperCase());
            		field.setType(type);
            		field.setComment(comment);
            		
            		if(StringUtils.isBlank(strfield)) {
            			strfield = Generators.fieldname(comment);
            		}
            		
            		field.setField(strfield);
            		
            		modelEdgeLine.getFields().add(field);
            	}
            }
    	};
    }
    
    private RowHandler analysisEdge(List<ModelEdgeLine> mes, 
    		Map<String,OntologyRelation> ontologyRelations, Long ontologyId) {
    	
    	return new RowHandler() {
            @Override
            public void handle(int sheetIndex, long rowIndex, List<Object> rowlist) {
            	if(rowIndex > 0) {
            		
            		Object index = rowlist.get(0);
            		if(index == null || StringUtils.isBlank(index.toString())) {
            			return;
            		}
            		
            		ModelEdgeLine mx = new ModelEdgeLine();
            		mx.setOntologyId(ontologyId);
            		
            		String label = rowlist.get(1)!= null?rowlist.get(1).toString():null;
            		String srcId = rowlist.get(2)!= null?rowlist.get(2).toString():null;
            		String dstId= rowlist.get(3)!= null?rowlist.get(3).toString():null;
            		
            		if(StringUtils.isBlank(label)) {
            			return;
            		}
            		
            		/**
            		 * 添加mysql对象
            		 */
            		OntologyRelation relation = new OntologyRelation();
            		relation.setOntologyId(ontologyId);
            		relation.setLabel(label);
            		ontologyRelations.put(label, relation);
            		
            		if(StringUtils.isBlank(srcId)) {
            			return;
            		}
            		if(StringUtils.isBlank(dstId)) {
            			return;
            		}
            		mx.setEdgeName(Generators.edgename(label));
            		mx.setLabel(label);
            		mx.setSrcId(Generators.ontologyVid(ontologyId, srcId));
            		mx.setDstId(Generators.ontologyVid(ontologyId, dstId));
            		mes.add(mx);
            	}
            }
    	};
    }
}
