package com.wb.common;

import com.ag.secp.platform.redis.PushCodeToRedis;
import com.ag.secp.platform.spring.SpringApplicationContext;
import com.wb.util.DbUtil;
import com.wb.util.StringUtil;
import org.apache.commons.collections4.CollectionUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class KVBuffer {
	private static List<String> jns=new ArrayList<String>();
	private static List<String> kvSql=new ArrayList<String>();
	private static List<String> codSql=new ArrayList<String>();
	//定义缓存类型 1.JavaType 通过Java程序存储缓存 2.RedisType 通过Redis缓存读取数据
	private static String BUFFER_TYPE="RedisType";
	/**
	 * 键值数据缓存。
	 */
	public static ConcurrentHashMap<String, ConcurrentHashMap<Object, String>> buffer;

	/**
	 * 获取指定键值的键值项列表数组组成的字符串。
	 * @param //key 键名称。
	 * @return 键值项列表。
	 */
	public static String getList(String keyName) {
		String strList= "";
		if (BUFFER_TYPE.equals("RedisType")){
			//处理redis
			strList = getRedisList(keyName);
		}else{
			//处理Java程序
			strList = getJavaList(keyName);
		}
		return strList;
	}

	/**
	 * 获取指定键值的键值项列表数组组成的字符串。
	 * @param //key 键名称。
	 * @return 键值项列表。
	 */
	public static String getJavaList(String keyName) {
		ConcurrentHashMap<Object, String> map = buffer.get(keyName);
		if (map == null)
			return "[]";
		StringBuilder buf = new StringBuilder();
		Set<Entry<Object, String>> es = map.entrySet();
		boolean isFirst = true;
		Object K;
		String V;
		buf.append("[");
		for (Entry<Object, String> e : es) {
			if (isFirst)
				isFirst = false;
			else
				buf.append(",");
			buf.append("{\"K\":");
			K = e.getKey();
			if (K instanceof Integer)
				buf.append(Integer.toString((Integer) K));
			else
				buf.append(StringUtil.quote((String) K));
			buf.append(",\"V\":");
			V = e.getValue();
			if (V.startsWith("@"))
				V = V.substring(1);
			else
				V = StringUtil.quote(V);
			buf.append(V);
			buf.append("}");
		}
		buf.append("]");
		return buf.toString();
	}

	/**
	 * 获取指定键值的键值项列表数组组成的字符串。
	 * @param //key 键名称。
	 * @return 键值项列表。
	 */
	/**
	 * 获取指定键值的键值项列表数组组成的字符串。
	 * @param //key 键名称。
	 * @return 键值项列表。
	 */
	public static String getRedisList(String keyName) {
		PushCodeToRedis redisBean= (PushCodeToRedis) SpringApplicationContext.getBean("pushCodeToRedis");
		//ConcurrentHashMap<Object, String> map = buffer.get(keyName);
		List<KvBean> kvBeanList=redisBean.getKvListFromRedis(keyName);
		if (CollectionUtils.isEmpty(kvBeanList))
			return "[]";
		StringBuilder buf = new StringBuilder();
		Object K;
		String V;
		buf.append("[");
		for (int i = 0; i <kvBeanList.size() ; i++) {
			K=kvBeanList.get(i).getK();
			buf.append("{\"K\":");
			if (K instanceof Integer){
				buf.append(Integer.toString((Integer) K));
			} else{
				buf.append(StringUtil.quote((String) K));
			}
			//V=kvBeanList.get(i).getV();
			V = StringUtil.quote(kvBeanList.get(i).getV());
			buf.append(",\"V\":");
			buf.append(V);
			if (i==kvBeanList.size()-1){
				buf.append("}");
			}else{
				buf.append("},");
			}
		}
		buf.append("]");
		return buf.toString();
	}

	/**
	 * 加载和初始化。
	 */
	public static synchronized void load(){
		if (BUFFER_TYPE.equals("RedisType")){
			//处理redis
			loadRedis();
		}else{
			//处理Java程序
			loadRedis();
		}
	}

	/**
	 * 加载和初始化。
	 */
	public static synchronized void loadJava() {
		try {
			buffer = new ConcurrentHashMap<String, ConcurrentHashMap<Object, String>>();
			Connection conn = null;
			Statement st = null;
			ResultSet rs = null;
			String K, keyName = null, preKeyName = null;
			ConcurrentHashMap<Object, String> map = new ConcurrentHashMap<Object, String>();

			try {
				//getSqlS("ilog_code");
				getSqlS("default");
				CodeBuffer.load(jns,codSql);
				//CodeBuffer.load();
				conn = DbUtil.getConnection();
				st = conn.createStatement();
				rs = st.executeQuery("select KEY_ID,KEY_NAME, key_name key_note,K,V,TYPE from  WB_KEY order  by  KEY_NAME  ");
				while (rs.next()) {
					keyName = rs.getString("KEY_NAME");
					if (preKeyName != null && !preKeyName.equals(keyName)) {
						buffer.put(preKeyName, map);
						map = new ConcurrentHashMap<Object, String>();
					}
					K = rs.getString("K");
					map.put(rs.getInt("TYPE") == 1 ? K : Integer.parseInt(K),
							rs.getString("V"));
					preKeyName = keyName;
				}
				if (preKeyName != null)
					buffer.put(preKeyName, map);
				for (int  i=0;i<jns.size();i++)
				{
					System.out.println(kvSql.get(i));
					loadWbKey(jns.get(i),kvSql.get(i));
				}
			} finally {
				DbUtil.close(rs);
				DbUtil.close(st);
				DbUtil.close(conn);
			}
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 加载和初始化。
	 */
	public static synchronized void loadRedis() {
		PushCodeToRedis redisBean = (PushCodeToRedis) SpringApplicationContext.getBean("pushCodeToRedis");
		redisBean.redisLoad();
	}

	//不同数据源 加载对应CODE 放入wbKey中
	public static  void loadWbKey(String Jndi,String sql) {
		try {
			Connection conn = null;
			Statement st = null;
			ResultSet rs = null;
			String K, keyName = null, preKeyName = null;
			ConcurrentHashMap<Object, String> map = new ConcurrentHashMap<Object, String>();

			try {
				conn = DbUtil.getConnection(Jndi);
				st = conn.createStatement();
				rs = st.executeQuery(sql);
				while (rs.next()) {
					keyName = rs.getString("KEY_NAME");
					if (preKeyName != null && !preKeyName.equals(keyName)) {
						buffer.put(preKeyName, map);
						map = new ConcurrentHashMap<Object, String>();
					}
					K = rs.getString("K");
					map.put( K ,rs.getString("V"));
					preKeyName = keyName;
				}
				if (preKeyName != null)
					buffer.put(preKeyName, map);
			} finally {
				DbUtil.close(rs);
				DbUtil.close(st);
				DbUtil.close(conn);
			}
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
	}




	/**
	 * 获取指定键对应的值。
	 * @param map 键值对照map。
	 * @param key 键。
	 * @return 键对应的字符串值。
	 */
	public static String getValue(ConcurrentHashMap<?, ?> map, Object key) {
		Object value;
		if (key == null)
			return null;
		if (key instanceof Number)
			value = map.get(((Number) key).intValue());
		else
			value = map.get(key.toString());
		if (value == null)
			return key.toString();
		else
			return value.toString();
	}
	public static String getValue(List<KvBean> list, Object key) {
		Object value;

		if (key == null){
			return null;
		}
		if (key.equals("")){
			value=key.toString();
		}else {
			List<KvBean> voList=list.stream().filter(bean->bean.getK().equals(key)).collect(Collectors.toList());
			if (CollectionUtils.isEmpty(voList)){
				value=key;
			}else{
				value=voList.get(0).getV();
			}
		}
		if (value == null)
			return key.toString();
		else
			return value.toString();
	}
	private static void getSqlS(String jndi) {

		Connection conn = null;
		Statement st = null;
		ResultSet rs = null;
		String jnid=null;
		int i=0;
		List<String>  jn=new ArrayList<String>();
		List<String>  kvsqls=new ArrayList<String>();
		List<String>  codSqls=new ArrayList<String>();
		try {
			String  kvSql = "",
					codSql= "";
			conn = DbUtil.getConnection(jndi);
			st = conn.createStatement();
			rs = st.executeQuery("select KV_SQL ,COD_SQL,JNDI from  CODE_SET  order by JNDI,TABLE_NAME");
			while (rs.next()) {
				if (jnid != null && !jnid.equals(rs.getString("JNDI"))) {
					jn.add(i, jnid);
					kvsqls.add(i, "select  * from  ("+kvSql+")   order by KEY_NAME");
					codSqls.add(i, "select  * from  ("+codSql+")   order by KEY_NAME");
					kvSql="";
					codSql="";
					i++;
				}
				if(jnid==null||!jnid.equals(rs.getString("JNDI")))
				{
					kvSql += rs.getString("KV_SQL");
					codSql +=rs.getString("COD_SQL");
				}
				else{
					kvSql += " union all "+rs.getString("KV_SQL");
					codSql +=" union all "+ rs.getString("COD_SQL");
				}
				jnid= rs.getString("JNDI");
			}
			if (jnid != null){
				jn.add(i, jnid);
				kvsqls.add(i, "select  * from  ("+kvSql+")   order by KEY_NAME");
				codSqls.add(i, "select  * from  ("+codSql+")   order by KEY_NAME");
			}


		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			jns=jn;
			kvSql=kvsqls;
			codSql=codSqls;
			DbUtil.close(rs);
			DbUtil.close(st);
			DbUtil.close(conn);
		}
	}


}