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

import java.io.InputStream;
import java.util.ArrayList;
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.nebula.graph.bean.NebulaEdge;
import com.wx.application.nebula.graph.bean.NebulaField;
import com.wx.application.nebula.graph.bean.NebulaIndex;
import com.wx.application.nebula.graph.bean.NebulaTag;
import com.wx.application.nebula.graph.enums.DataType;
import com.wx.application.nebula.graph.enums.IndexType;
import com.wx.application.util.InputStreamCache;

import cn.hutool.core.util.HashUtil;
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 ImportSchemaService {
	
	@Autowired
	NebulaOperateService nebulaOperateService;
	
	/**
     * 导入数据解析excel
     */
    public void analysisExcel(String space, InputStream in) {
    	
    	InputStreamCache inCache = new InputStreamCache(in);
    	
    	List<NebulaTag> mxs = new ArrayList<>();
    	List<NebulaEdge> mes = new ArrayList<>();
    	
    	ExcelReader reader = ExcelUtil.getReader(inCache.getInputStream());
    	List<String> sns = reader.getSheetNames();
    	for(int i=0;i<sns.size();i++) {
    		switch (sns.get(i)) {
			/*case "tag":
				ExcelUtil.readBySax(inCache.getInputStream(), i, analysisTag(mxs));
				break;*/
			case "edge":
				ExcelUtil.readBySax(inCache.getInputStream(), i, analysisEdge(mes));
				break;
			/*case "tag属性":
				ExcelUtil.readBySax(inCache.getInputStream(), i, analysisTagField(mxs));
				break;
			case "edge属性":
				ExcelUtil.readBySax(inCache.getInputStream(), i, analysisEdgeField(mes));
				break;*/
			default:
				break;
			}
    	}
    	reader.close();
    	inCache.destroyCache();
    	
    	/**
    	 * 执行导入
    	 */
    	mxs.forEach(v->{
    		try {
    			nebulaOperateService.createTag(space, v);
    			/**
    			 * 创建索引
    			 */
    			NebulaIndex e = new NebulaIndex();
    			e.setName("tagindex_" + v.getName());
    			e.setOnName(v.getName());
    			e.setType(IndexType.TAG);
    			nebulaOperateService.createIndex(space, e);
    			
    		} catch (Exception e) {
    			log.error("{}",e);
			}
    	});
    	
    	mes.forEach(v->{
    		try {
    			nebulaOperateService.createEdge(space, v);
    			/**
    			 * 创建索引
    			 */
    			NebulaIndex e = new NebulaIndex();
    			e.setName("edgeindex_" + v.getName());
    			e.setOnName(v.getName());
    			e.setType(IndexType.EDGE);
    			nebulaOperateService.createIndex(space, e);
	    	} catch (Exception e) {
				log.error("{}",e);
			}
    	});
    	
    }
	
    
    private RowHandler analysisTag(List<NebulaTag> mxs) {
    	
    	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;
            		}
            		
            		NebulaTag mx = new NebulaTag();
            		
            		String tagName = rowlist.get(1) != null?rowlist.get(1).toString():null;
            		String comment = rowlist.get(2) != null?rowlist.get(2).toString():null;
            		
            		if(StringUtils.isBlank(tagName)) {
            			
            			if(StringUtils.isBlank(comment)) {
                			return;
                		}
            			tagName = "tag_" + HashUtil.fnvHash(comment);
            		}
            		
            		mx.setName(tagName);
            		mx.setComment(comment);
            		
            		mxs.add(mx);
            	}
            }
    	};
    }
    
    private RowHandler analysisTagField(List<NebulaTag> mxs) {
    	
    	Map<String, NebulaTag> mvMap = mxs.stream().collect(
                Collectors.toMap(NebulaTag::getName, 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 tagName = rowlist.get(1) != null?rowlist.get(1).toString():null;
            		String comment = rowlist.get(2) != null?rowlist.get(2).toString():null;
            		
            		if(StringUtils.isBlank(tagName)) {
            			if(StringUtils.isBlank(comment)) {
                			return;
                		}
            			tagName = "tag_" + HashUtil.fnvHash(comment);
            		}
            		
            		NebulaTag nebulaTag = mvMap.get(tagName);
            		if(nebulaTag == null) {
            			return;
            		}
            		
            		if(nebulaTag.getFields() == null) {
            			nebulaTag.setFields(new ArrayList<>());
            		}
            		NebulaField field = new NebulaField();
            		
            		String Field = rowlist.get(3) != null?rowlist.get(3).toString():null;
            		String strtype = rowlist.get(4) != null?rowlist.get(4).toString():null;
            		String fieldcomment = rowlist.get(5) != null?rowlist.get(5).toString():null;
            		
            		if(StringUtils.isBlank(Field)) {
            			if(StringUtils.isBlank(fieldcomment)) {
                			return;
                		}
            			Field = "field_" + HashUtil.fnvHash(fieldcomment);
            		}
            		
            		field.setField(Field);
            		
            		if(StringUtils.isBlank(strtype)) {
            			strtype = "STRING";
            		}
            		DataType type = DataType.valueOf(strtype.toUpperCase());
            		field.setType(type);
            		field.setComment(fieldcomment);
            		nebulaTag.getFields().add(field);
            	}
            }
    	};
    }
    
    
    private RowHandler analysisEdgeField(List<NebulaEdge> mes) {
    	
    	Map<String, NebulaEdge> mvMap = mes.stream().collect(
                Collectors.toMap(NebulaEdge::getName, 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 edgeName = rowlist.get(1) != null?rowlist.get(1).toString():null;
            		String comment = rowlist.get(2) != null?rowlist.get(2).toString():null;
            		
            		if(StringUtils.isBlank(edgeName)) {
            			if(StringUtils.isBlank(comment)) {
                			return;
                		}
            			edgeName = "edge_" + HashUtil.fnvHash(comment);
            		}
            		
            		NebulaEdge nebulaEdge = mvMap.get(edgeName);
            		if(nebulaEdge == null) {
            			return;
            		}
            		
            		if(nebulaEdge.getFields() == null) {
            			nebulaEdge.setFields(new ArrayList<>());
            		}
            		NebulaField field = new NebulaField();
            		
            		String Field = rowlist.get(3) != null?rowlist.get(3).toString():null;
            		String strtype = rowlist.get(4) != null?rowlist.get(4).toString():null;
            		String fieldcomment = rowlist.get(5) != null?rowlist.get(5).toString():null;
            		
            		if(StringUtils.isBlank(Field)) {
            			if(StringUtils.isBlank(fieldcomment)) {
                			return;
                		}
            			Field = "field_" + HashUtil.fnvHash(fieldcomment);
            		}
            		
            		field.setField(Field);
            		
            		if(StringUtils.isBlank(strtype)) {
            			strtype = "STRING";
            		}
            		DataType type = DataType.valueOf(strtype.toUpperCase());
            		field.setType(type);
            		field.setComment(rowlist.get(4).toString());
            		nebulaEdge.getFields().add(field);
            	}
            }
    	};
    }
    
    private RowHandler analysisEdge(List<NebulaEdge> mes) {
    	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;
            		}
            		
            		NebulaEdge mx = new NebulaEdge();
            		
            		String edgeName = rowlist.get(1)!= null?rowlist.get(1).toString():null;
            		String comment = rowlist.get(2)!= null?rowlist.get(2).toString():null;
            		
            		if(StringUtils.isBlank(edgeName)) {
            			if(StringUtils.isBlank(comment)) {
                			return;
                		}
            			edgeName = "edge_" + HashUtil.fnvHash(comment);
            		}
            		
            		mx.setName(edgeName);
            		mx.setComment(comment);

            		mes.add(mx);
            	}
            }
    	};
    }
}
