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

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.vesoft.nebula.client.graph.data.Node;
import com.vesoft.nebula.client.graph.data.PathWrapper;
import com.vesoft.nebula.client.graph.data.Relationship;
import com.vesoft.nebula.client.graph.data.ResultSet;
import com.vesoft.nebula.client.graph.data.ValueWrapper;
import com.wx.application.nebula.graph.query.NebulaModel;
import com.wx.application.nebula.graph.query.NebulaNode;
import com.wx.application.nebula.graph.query.NebulaRelation;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

public class ResultSetUtils {
	
	/**
	 * 结果集打印 Path
	 * @param resultSet
	 * @throws UnsupportedEncodingException
	 */
	public static NebulaModel printResultPath(ResultSet resultSet) {
		
		Set<NebulaNode> ns = new HashSet<>();
		Set<NebulaRelation> rls = new HashSet<>();
		
		try {
			
			NebulaNode node = null;
			NebulaRelation relation = null;
			
			for (int i = 0; i<resultSet.rowsSize(); i++) {
	            ResultSet.Record record = resultSet.rowValues(i);
	            for (ValueWrapper value : record.values()) {
	            	
	            	if (value.isPath()) {
	            		/**
	            		 * 处理节点
	            		 */
	                	PathWrapper pw = value.asPath();
	                	List<Node> nodes = pw.getNodes();
	                	for(Node nd : nodes) {
	                		List<String> labels = nd.labels();
	                		node = new NebulaNode();
	                		node.setVid(nd.getId().asString());
	                		node.setLabels(labels.get(0));
	                		node.setProperties(nd.properties(labels.get(0)));
	                		/**
							 * 处理快照
							 */
							printnebulafieldsnapshot(node.getProperties());
	                		
	                		ns.add(node);
	                	}
	                	/**
	            		 * 处理关系
	            		 */
	                	List<Relationship> rs = pw.getRelationships();
	                	for(Relationship r:rs) {
	                		relation = new NebulaRelation();
	                		relation.setSrcId(r.srcId().asString());
	                		relation.setDstId(r.dstId().asString());
	                		relation.setEdgeName(r.edgeName());
	                		relation.setProperties(r.properties());
	                		
	                		/**
							 * 处理快照
							 */
							printnebulafieldsnapshot(relation.getProperties());
	                		
	                		rls.add(relation);
	                	}
	                    
	                }
	            	
	            }
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		NebulaModel ml = new NebulaModel();
		ml.setNodes(new ArrayList<>(ns));
		ml.setRelations(new ArrayList<>(rls));

		return ml;
	}
	
	/**
	 * 结果集打印Vertex
	 * @param resultSet
	 * @throws UnsupportedEncodingException
	 */
	public static List<NebulaNode> printResultVertex(ResultSet resultSet) {
		
		List<NebulaNode> ns = new ArrayList<>();
		
		try {
			
			NebulaNode node = null;
			
			for (int i = 0; i<resultSet.rowsSize(); i++) {
	            ResultSet.Record record = resultSet.rowValues(i);
	            for (ValueWrapper value : record.values()) {
	            	if (value.isVertex()) {
	            		/**
	            		 * 处理节点
	            		 */
	            		Node nd = value.asNode();
	            		List<String> labels = nd.labels();
	            		node = new NebulaNode();
                		node.setVid(nd.getId().asString());
                		node.setLabels(labels.get(0));
                		node.setProperties(nd.properties(labels.get(0)));
                		
                		/**
						 * 处理快照
						 */
						printnebulafieldsnapshot(node.getProperties());
                		
                		ns.add(node);
	                }
	            }
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return ns;
	}

	
	/**
	 * 结果集打印Vertex
	 * @param resultSet
	 * @throws UnsupportedEncodingException
	 */
	public static List<NebulaRelation> printResultRelation(ResultSet resultSet) {
		List<NebulaRelation> ns = new ArrayList<>();
		try {
			for (int i = 0; i<resultSet.rowsSize(); i++) {
	            ResultSet.Record record = resultSet.rowValues(i);
	            for (ValueWrapper value : record.values()) {
	            	
	            	if (value.isEdge()) {
	                    /**
	            		 * 处理关系
	            		 */
	                	Relationship r = value.asRelationship();
	                	NebulaRelation relation = new NebulaRelation();
                		relation.setSrcId(r.srcId().asString());
                		relation.setDstId(r.dstId().asString());
                		relation.setEdgeName(r.edgeName());
                		relation.setProperties(r.properties());
                		/**
						 * 处理快照
						 */
						printnebulafieldsnapshot(relation.getProperties());
						ns.add(relation);
	                }
	            }
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return ns;
	}
	
	/**
	 * 结果集打印Vertex
	 * @param resultSet
	 * @throws UnsupportedEncodingException
	 */
	public static List<JSONObject> printResultObject(ResultSet resultSet) {
		
		List<JSONObject> ns = new ArrayList<>();

		try {
			List<String> colNames = resultSet.keys();
			for (int i = 0; i<resultSet.rowsSize(); i++) {
	            ResultSet.Record record = resultSet.rowValues(i);
	            int k = 0;
	            for (ValueWrapper value : record.values()) {
	            	JSONObject obj = new JSONObject();
	            	String key = colNames.get(k);
	            	if (value.isList()) {
	                	List<Object> list = new ArrayList<>();
	                	for (ValueWrapper fn : value.asList()) {
	                		list.add(printValueWrapper(fn));
	                	}
	                	obj.set(key, list);
	                } else if (value.isSet()) {
	                	List<Object> list = new ArrayList<>();
	                	for (ValueWrapper fn : value.asSet()) {
	                		list.add(printValueWrapper(fn));
	                	}
	                	obj.set(key, list);
	                } else if (value.isMap()) {
	                	obj.set(key, value.asMap());
	                } else {
	                	obj.set(key, printValueWrapper(value));
	                }
	                k++;
	                ns.add(obj);
	            }
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ns;
	}
	
	
	public static List<JSONObject> printResultObject(ResultSet resultSet,Integer split) {
		List<JSONObject> ots = printResultObject(resultSet);
		int i = 0;
		List<JSONObject> rs = new ArrayList<>();
		JSONObject jt = null;
		for(JSONObject fn : ots) {
			if(i % split == 0) {
				jt = new JSONObject();
				rs.add(jt);
			}
			JSONObject item = new JSONObject();
			for(String ky:fn.keySet()) {
				item.set(ky.toLowerCase(), fn.get(ky));
			}
			jt.putAll(item);
			i++;
		}
		return rs;
	}
	
	
	public static void printnebulafieldsnapshot(JSONObject properties) {
		/**
		 * 快照转换
		 */
		properties.forEach((k,v)-> {
			if(v instanceof String) {
				String snapshot = properties.getStr(k);
				if(JSONUtil.isTypeJSONArray(snapshot)) {
					properties.set(k, JSONUtil.parseArray(snapshot));
				} else if (JSONUtil.isTypeJSONObject(snapshot)) {
					properties.set(k, JSONUtil.parseObj(snapshot));
				}
			}
		});
	}
	
	public static Object printValueWrapper(ValueWrapper value) {
		
		try {
			if (value.isLong()) {
	    		return value.asLong();
	        } else if (value.isBoolean()) {
	        	return value.asBoolean();
	        } else if (value.isDouble()) {
	        	return value.asDouble();
	        } else if (value.isString()) {
	        	return value.asString();
	        } else if (value.isTime()) {
	        	return value.asTime();
	        } else if (value.isDate()) {
	        	return value.asDate();
	        } else if (value.isDateTime()) {
	        	return value.asDateTime();
	        } 
		} catch (Exception e) {
			// TODO: handle exception
		}
		return null;
	}
	
}
