package org.diagbot.graph.util;

import org.diagbot.graph.encryption.DESUtil;
import org.neo4j.driver.v1.*;
import org.neo4j.graphdb.RelationshipType;

import java.util.HashMap;
import java.util.Map;

import static org.neo4j.driver.v1.Values.parameters;

/**
 * 节点,关系库
 * Created by DELL on 2018/11/26.
 */
public class NodeRelationUtil {
    private static Driver driver;
    private static Map<String, String> RelaType = new HashMap<>();
    private enum RelType implements RelationshipType {
        is_a, equal
    }

    /**
     * 获取driver
     * @return
     */
    public Driver getDriver(){
        ConnectionNeo4j connectionNeo4j = new ConnectionNeo4j();
        driver=connectionNeo4j.connectionNeo4j();
        return driver;
    }
    public Driver get232Driver(){
        ConnectionNeo4j connectionNeo4j = new ConnectionNeo4j();
        driver=connectionNeo4j.connection232Neo4j();
        return driver;
    }

    /**
     * 创建节点,节点不带属性
     * @param lbl 标签名字
     * @param val 节点名字
     */
    public void AddNode(final Driver driver,final Integer sign, final String lbl, final String val) {
        Session session = null;
        try {
            session = driver.session(AccessMode.WRITE);
            session.writeTransaction(new TransactionWork<Integer>() {
                @Override
                public Integer execute(Transaction tx) {
                    String query =null;
                    int result =0;
                    if(sign == 0){
                        query = "MERGE (n:" + lbl + "{name:$name}) RETURN n";
                        result = processNode(tx, query, "name", val);
                    }else if (sign == 1){
                        query = "MERGE (n:" + DESUtil.encrypt(lbl,DESUtil.KEY_LANTONE) + "{name:$name}) RETURN n";
                        result = processNode(tx, query, "name", DESUtil.encrypt(val,DESUtil.KEY_LANTONE));
                    }
                    return result;
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }
    /**
     * 创建节点,节点带属性
     * @param lbl 标签名字
     * @param val 节点名字
     */
    public void AddNode(final Driver driver, final String lbl, final String val, final Integer path) {

        Session session = null;


        try {
            session = driver.session(AccessMode.WRITE);
            session.writeTransaction(new TransactionWork<Integer>() {
                @Override
                public Integer execute(Transaction tx) {
                    String query = "MERGE (n:" + lbl + "{name:$name,path:$path}) RETURN n";
                    int result = processNodepro(tx, query, "name", val,"path",path);
                    return result;
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }
    /**
     * 创建节点,节点带属性
     * @param lbl 标签名字
     * @param val 节点名字
     */
    public void AddNode(final Driver driver,final Integer sign, final String lbl, final String val, final Integer path, final String relation) {
        Session session = null;

        try {
            session = driver.session(AccessMode.WRITE);
            session.writeTransaction(new TransactionWork<Integer>() {
                @Override
                public Integer execute(Transaction tx) {
                    String query =null;
                    int result =0;
                    if(sign == 0){
                        query = "MERGE (n:" + lbl + "{name:$val,path:$path,relation:$relation}) RETURN n";
                        result = processNodepro(tx, query, "val",val,"path",path,"relation",relation);
                    }else if (sign == 1){
                        query = "MERGE (n:" + DESUtil.encrypt(lbl,DESUtil.KEY_LANTONE) + "{name:$val,path:$path,relation:$relation}) RETURN n";
                        result = processNodepro(tx, query, "val", DESUtil.encrypt(val,DESUtil.KEY_LANTONE),"path",path,"relation",relation);
                    }
                    return result;
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }
    /**
     * 添加带属性的关系
     */
    public void addRelationWithProperty(final Driver driver, final String fromlbl, final String fromval, final String relation,final Integer sort, final String tolbl, final String toval){
        Session session = null;
        try {
            session = driver.session(AccessMode.WRITE);
            session.writeTransaction(new TransactionWork<Integer>() {
                @Override
                public Integer execute(Transaction tx) {
                    int result =0;
                    String query = "MATCH (e:" + fromlbl + "{name:$src}), (c:" + tolbl + "{name:$dest}) " +
                            "MERGE (e)-[r:" + relation + "{p:"+sort+"}]->(c) RETURN e.name, type(r), c.name";
                    result = processRelation(tx, query, "src", fromval, "dest", toval);
                    return result;
                }
            });
        }catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }
    /**
     * 添加带属性的关系
     */
    public void addRelationWithPropertyDouble(final Driver driver, final String fromlbl, final String fromval, final String relation,final Double sort, final String tolbl, final String toval){
        Session session = null;
        try {
            session = driver.session(AccessMode.WRITE);
            session.writeTransaction(new TransactionWork<Integer>() {
                @Override
                public Integer execute(Transaction tx) {
                    int result =0;
                    String query = "MATCH (e:" + fromlbl + "{name:$src}), (c:" + tolbl + "{name:$dest}) " +
                            "MERGE (e)-[r:" + relation + "{rate:"+sort+"}]->(c) RETURN e.name, type(r), c.name";
                    result = processRelation(tx, query, "src", fromval, "dest", toval);
                    return result;
                }
            });
        }catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }
    /**
     * 为两个节点添加关系
     * @param fromlbl 标签类型
     * @param fromval 节点名字
     * @param relation 关系
     * @param tolbl 标签类型
     * @param toval 节点名字
     */
    public void addRelation(final Driver driver,final Integer sign, final String fromlbl, final String fromval, final String relation, final String tolbl, final String toval){
        Session session = null;
        //两个节点之间,有关系,先删除
        try {
            session = driver.session(AccessMode.WRITE);
            //为两个节点添加关系
            session.writeTransaction(new TransactionWork<Integer>() {
                @Override
                public Integer execute(Transaction tx) {
                    String query =null;
                    int result =0;
                    if(sign == 0){
                        query = "MATCH (e:" + fromlbl + "{name:$src}), (c:" + tolbl + "{name:$dest}) " +
                                "MERGE (e)-[r:" + relation + "]->(c) RETURN e.name, type(r), c.name";
                        result = processRelation(tx, query, "src", fromval, "dest", toval);
                    }else if (sign == 1){
                        query = "MATCH (e:" + DESUtil.encrypt(fromlbl,DESUtil.KEY_LANTONE) + "{name:$src}), (c:" + DESUtil.encrypt(tolbl,DESUtil.KEY_LANTONE) + "{name:$dest}) " +
                                "MERGE (e)-[r:" + DESUtil.encrypt(relation,DESUtil.KEY_LANTONE) + "]->(c) RETURN e.name, type(r), c.name";
                        result = processRelation(tx, query, "src", DESUtil.encrypt(fromval,DESUtil.KEY_LANTONE), "dest", DESUtil.encrypt(toval,DESUtil.KEY_LANTONE));
                    }
                    return result;
                }
            });
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null) session.close();
        }
    }

    private int processRelation(Transaction tx, String query, String srclbl,
                                String srcname, String destlbl, String destname) {
        tx.run(query, parameters(srclbl, srcname, destlbl, destname));
        return 1;
    }

    private int processNode(Transaction tx, String query, String label, String val) {
        tx.run(query, parameters(label, val));
        return 1;
    }
    //带属性
    private int processNodepro(Transaction tx, String query, String label, String val, String parm, Integer path) {
        tx.run(query, parameters(label, val,parm,path));
        return 1;
    }
    //带属性
    private int processNodepro(Transaction tx, String query, String label, String val, String parm, Integer path, String relation, String relation1) {
        tx.run(query, parameters(label, val,parm,path,relation,relation1));
        return 1;
    }
}
