package com.saga.util;

import java.io.File;
import java.io.FileReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.zillion.util.log.LogUtil;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.saga.entity.Data;
import com.saga.entity.PointSet;
import com.saga.entity.Record;
import com.zillion.database.agent.ZillionAgent;

public class Constant {
	public static int PacketId = 0;
	public static int InsertThread = 1;
	public static ZillionAgent agent;
	public static boolean DBConn = true;
	public static String WaitingTimeControl = "5Second";
	public static File setlog = new File(System.getProperty("user.dir") + "/setlog.log");
	public static List<String> CollectReportList = new ArrayList<String>();

	public static List<Record> RecordListToDB = new ArrayList<Record>();
	public static Map<String, String> Meter_Collector = new HashMap<String, String>();
	public static Map<String, String> Meter_Collector_Control = new HashMap<String, String>();
	public static List<PointSet> pointSetList = new ArrayList<PointSet>();
	// public static Map<String, String> CollectorPointSetList = new
	// HashMap<String, String>();
	public static Map<String, String> BuildingDB = new HashMap<String, String>();
	public static String defaultDB;
	public static Map<String, String> BuildingConv = new HashMap<String, String>();
	public static Map<String, List<String>> BuildingAdds = new HashMap<String, List<String>>();
	public static Map<String, String> TypePort = new HashMap<String, String>();
	public static Map<Integer, String> PortCompress = new HashMap<Integer, String>();
	public static Map<Integer, String> PortHistory = new HashMap<Integer, String>();
	public static Map<String, Integer> RecordAddress = new HashMap<String, Integer>();
	public static List<Record> RecordList = new ArrayList<Record>();

	// public static Map<String, Long> ps_NodeStatus = new HashMap<String,
	// Long>();
	public static Map<String, Long> ps_PointStatusUp = new HashMap<String, Long>();
	public static Map<String, Long> ps_PhysicalStatus = new HashMap<String, Long>();
	public static Map<String, Long> ps_ProjectStatus = new HashMap<String, Long>();
	public static Map<String, Long> ps_MeterStatusUp = new HashMap<String, Long>();
	public static Map<String, Long> ps_PointStatusDown = new HashMap<String, Long>();
	public static Map<String, Long> ps_MeterStatusDown = new HashMap<String, Long>();

	public static Map<String, List<String>> ps_PhysicalList = new HashMap<String, List<String>>();
	public static Map<String, List<String>> ps_ProjectList = new HashMap<String, List<String>>();
	public static Map<String, List<String>> ps_MeterList = new HashMap<String, List<String>>();

	public static Map<String, String> pointInfo = new HashMap<String, String>();
	public static Map<String, Data> nodeCache = new HashMap<String, Data>();
	public static Map<String, Data> pointCache = new HashMap<String, Data>();
	// public static Map<String, Long> pointListDown = new HashMap<String,
	// Long>();
	public static Map<String, Long> ps_ID2Time = new HashMap<String, Long>();
	public static Map<String, String> ps_ID2Point = new HashMap<String, String>();
	public static Map<String, String> ps_ID2Function = new HashMap<String, String>();
	public static Map<String, String> ps_ID2Status = new HashMap<String, String>();
	public static int collectRec = 0;
	public static int collectSend = 0;
	public static int sendRec = 0;
	public static int sendSend = 0;
	public static int writeDB = 0;
	public static int collectCount = 0;
	public static int collectReportCount = 0;
	public static int report2DBCount = 0;
	public static Map<String, String> pointMAC = new HashMap<String, String>();

	static {
		String resource = "\\config.json";
		String path = null;
		JsonParser config = new JsonParser();

		try {
			LogUtil.info("System.get " + System.getProperty("user.dir") + resource);
			LogUtil.info("LogUtil.get " + LogUtil.GetPath() + resource);
			path = LogUtil.GetPath() + resource;

			JsonObject object = (JsonObject) config.parse(new FileReader(path));

			JsonArray db = object.get("DB").getAsJsonArray();
			for (int i = 0; i < db.size(); i++) {
				JsonObject subObject = db.get(i).getAsJsonObject();
				if (subObject.get("building") != null) {
					String building = subObject.get("building").getAsString();
					Constant.BuildingDB.put(building, subObject.get("database").getAsString());
					Constant.defaultDB = subObject.get("database").getAsString();

					if (subObject.get("buildingadds") != null) {
						JsonArray buildingAdds = subObject.get("buildingadds").getAsJsonArray();
						for (int j = 0; j < buildingAdds.size(); j++) {
							JsonObject addObject = buildingAdds.get(j).getAsJsonObject();
							if (!Constant.BuildingAdds.containsKey(building)) {
								Constant.BuildingAdds.put(building, new ArrayList<String>());
							}
							Constant.BuildingAdds.get(building).add(addObject.get("building").getAsString());
							Constant.BuildingDB.put(addObject.get("building").getAsString(),
									subObject.get("database").getAsString());
							Constant.defaultDB = subObject.get("database").getAsString();
							Constant.BuildingConv.put(addObject.get("building").getAsString(), building);
						}

					}
				} else if (subObject.get("insertthread") != null) {
					Constant.InsertThread = subObject.get("insertthread").getAsInt();
				}
			}
			JsonArray port = object.get("Port").getAsJsonArray();
			for (int i = 0; i < port.size(); i++) {
				JsonObject subObject = port.get(i).getAsJsonObject();
				String ports = subObject.get("port").getAsString();
				Constant.TypePort.put(subObject.get("type").getAsString(), ports);
				Constant.PortCompress.put(Integer.valueOf(ports), subObject.get("Compress").getAsString());
				Constant.PortHistory.put(Integer.valueOf(ports), subObject.get("History").getAsString());
				// for (String p : ports.split(",")) {
				// Constant.PortCompress.put(Integer.valueOf(p),
				// subObject.get("Compress").getAsString());
				// Constant.PortHistory.put(Integer.valueOf(p),
				// subObject.get("History").getAsString());
				// }
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			// System.out.println(e.getMessage());
			LogUtil.warn(e.toString());
			LogUtil.warn("No Config File(config.json) in " + path + ",Now Exit!");
			System.exit(0);
		}

	}

	// public static long getWaitingtime() {
	// // TODO Auto-generated method stub
	// try {
	// if (WaitingTimeControl.contains("Second")) {
	// return Integer.valueOf(WaitingTimeControl.replace(" ",
	// "").replace("Second", ""))
	// * Constant.Millisecond.SECOND_1;
	// } else if (WaitingTimeControl.contains("second")) {
	// return Integer.valueOf(WaitingTimeControl.replace(" ",
	// "").replace("second", ""))
	// * Constant.Millisecond.SECOND_1;
	// } else {
	// return Constant.Millisecond.SECOND_3;
	// }
	// } catch (Exception e) {
	// return Constant.Millisecond.SECOND_3;
	// }
	// }

	public static long getWaitingtime() {
		// TODO Auto-generated method stub
		try {
			if (WaitingTimeControl.contains("Second")) {
				return Integer.valueOf(WaitingTimeControl.replace(" ", "").replace("Second", ""))
						* Constant.Millisecond.SECOND_1;
			} else if (WaitingTimeControl.contains("second")) {
				return Integer.valueOf(WaitingTimeControl.replace(" ", "").replace("second", ""))
						* Constant.Millisecond.SECOND_1;
			} else {
				return Constant.Millisecond.SECOND_3;
			}
		} catch (Exception e) {
			return Constant.Millisecond.SECOND_3;
		}
	}

	public static InetAddress getLocalHostLANAddress() throws UnknownHostException {
		try {
			InetAddress candidateAddress = null;
			// 遍历所有的网络接口
			for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
				NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
				// 在所有的接口下再遍历IP
				for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
					InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
					if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址
						if (inetAddr.isSiteLocalAddress()) {
							// 如果是site-local地址，就是它了
							return inetAddr;
						} else if (candidateAddress == null) {
							// site-local类型的地址未被发现，先记录候选地址
							candidateAddress = inetAddr;
						}
					}
				}
			}
			if (candidateAddress != null) {
				return candidateAddress;
			}
			// 如果没有发现 non-loopback地址.只能用最次选的方案
			InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
			if (jdkSuppliedAddress == null) {
				throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
			}
			return jdkSuppliedAddress;
		} catch (Exception e) {
			UnknownHostException unknownHostException = new UnknownHostException(
					"Failed to determine LAN address: " + e);
			unknownHostException.initCause(e);
			throw unknownHostException;
		}
	}

	private static final SimpleDateFormat SIMPLEDATEFORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
	private static final SimpleDateFormat SIMPLEDATEFORMATDB = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private static final SimpleDateFormat SIMPLEDATEFORMAT_Minute = new SimpleDateFormat("yyyyMMddHHmm");
	private static final SimpleDateFormat SIMPLEDATEFORMAT_DAY = new SimpleDateFormat("yyyyMMdd");
	private static final SimpleDateFormat SIMPLEDATEFORMATLOG = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
	// private static final SimpleDateFormat SIMPLEDATEFORMAT_LOG = new
	// SimpleDateFormat("yyyyMMddHHmmssSSS");

	// public synchronized static String format_LOG(Date value) {
	// return SIMPLEDATEFORMAT_LOG.format(value);
	// }

	public synchronized static String format_Minute(Date value) {
		return SIMPLEDATEFORMAT_Minute.format(value);
	}

	public synchronized static String format_DB(Date value) {
		return SIMPLEDATEFORMATDB.format(value);
	}

	public synchronized static String format_Log(Date value) {
		return SIMPLEDATEFORMATLOG.format(value);
	}

	// public synchronized static Date parse_LOG(String value) throws
	// ParseException {
	// return SIMPLEDATEFORMAT_LOG.parse(value);
	// }

	public synchronized static Date parse_Minute(String value) throws ParseException {
		return SIMPLEDATEFORMAT_Minute.parse(value);
	}

	public synchronized static Date parse_DB(String value) throws ParseException {
		return SIMPLEDATEFORMATDB.parse(value);
	}

	public synchronized static String format(Date value) {
		if (value == null) {
			return "null";
		}
		return SIMPLEDATEFORMAT.format(value);
	}

	public synchronized static Date parse(String value) throws ParseException {
		return SIMPLEDATEFORMAT.parse(value);
	}

	public synchronized static String format_day(Date value) {
		return SIMPLEDATEFORMAT_DAY.format(value);
	}

	public synchronized static Date parse_day(String value) throws ParseException {
		return SIMPLEDATEFORMAT_DAY.parse(value);
	}

	public static void showStatus() {
		// TODO Auto-generated method stub
		LogUtil.info("ps_PointStatusUp:");
		for (Entry<String, Long> d : Constant.ps_PointStatusUp.entrySet()) {
			LogUtil.info(d.getKey() + " " + Constant.format(new Date(d.getValue())));
		}
		LogUtil.info("-----------------------------------------------------");
		LogUtil.info("ps_PhysicalStatus:");
		for (Entry<String, Long> d : Constant.ps_PhysicalStatus.entrySet()) {
			LogUtil.info(d.getKey() + " " + Constant.format(new Date(d.getValue())));
		}
		LogUtil.info("-----------------------------------------------------");
		LogUtil.info("ps_ProjectStatus:");
		for (Entry<String, Long> d : Constant.ps_ProjectStatus.entrySet()) {
			LogUtil.info(d.getKey() + " " + Constant.format(new Date(d.getValue())));
		}
		LogUtil.info("-----------------------------------------------------");
		LogUtil.info("ps_MeterStatusUp:");
		for (Entry<String, Long> d : Constant.ps_MeterStatusUp.entrySet()) {
			LogUtil.info(d.getKey() + " " + Constant.format(new Date(d.getValue())));
		}
		LogUtil.info("-----------------------------------------------------");
		LogUtil.info("ps_PointStatusDown:");
		for (Entry<String, Long> d : Constant.ps_PointStatusDown.entrySet()) {
			LogUtil.info(d.getKey() + " " + Constant.format(new Date(d.getValue())));
		}
		LogUtil.info("-----------------------------------------------------");
		LogUtil.info("ps_MeterStatusDown:");
		for (Entry<String, Long> d : Constant.ps_MeterStatusDown.entrySet()) {
			LogUtil.info(d.getKey() + " " + Constant.format(new Date(d.getValue())));
		}
		LogUtil.info("-----------------------------------------------------");
		LogUtil.info("ps_PhysicalList:\n" + Constant.ps_PhysicalList);
		LogUtil.info("-----------------------------------------------------");
		LogUtil.info("ps_ProjectList:\n" + Constant.ps_ProjectList);
		LogUtil.info("-----------------------------------------------------");
		LogUtil.info("ps_MeterList:\n" + Constant.ps_MeterList);
		LogUtil.info("-----------------------------------------------------");

	}

	public static List<String> getConfigFile(String directoryPath, String directoryKey, String fileKey) {
		List<String> list = new ArrayList<String>();
		File baseFile = new File(directoryPath);
		if (baseFile.isFile() || !baseFile.exists()) {
			return list;
		}
		try {
			File[] files = baseFile.listFiles();
			SAXReader saxReader = new SAXReader();
			for (File file : files) {
				if (file.isDirectory() && file.getName().contains(directoryKey)) {
					list.addAll(getConfigFile(file.getAbsolutePath(), directoryKey, fileKey));
				} else {
					if (file.getName().contains(fileKey)) {
						list.add(file.getAbsolutePath());
						Document document = saxReader.read(file);
						List<Element> devList = document.selectNodes("/root/portdev/devtype");
						// System.out.println(file.getName());
						// System.out.println(file.getName().indexOf(fileKey));
						// System.out.println(file.getName().indexOf(".xml"));
						String port = file.getName().substring(file.getName().indexOf(fileKey) + fileKey.length(),
								file.getName().indexOf(".xml"));
						// System.out.println(port);
						// System.out.println(file.getParentFile().getName());
						// String building =
						// file.getParentFile().getName().replace(directoryKey,
						// "").substring(0, 10);
						// String mac =
						// file.getParentFile().getName().replace(directoryKey,
						// "").substring(10);
						String building = file.getParentFile().getName().replace(directoryKey, "").split("-")[0];
						String mac = file.getParentFile().getName().replace(directoryKey, "").split("-")[1];
						// System.out.println(building);
						// System.out.println(mac);

						for (Element portdev : devList) {
							String meter = portdev.attributeValue("meterid");
							String info = port + "-" + portdev.element("addr").getText();
							String point = building + "-" + mac + "-" + meter;
							Constant.pointInfo.put(point, info);
							// Iterator funcList =
							// portdev.selectNodes("funset/funid").iterator();
							// while (funcList.hasNext()) {
							// Element func = (Element) funcList.next();
							// String point = building + "-" + mac + "-" + meter
							// + "." + func.getText();
							// String info = port + "-" +
							// portdev.element("addr").getText();
							// Constant.pointInfo.put(point, info);
							// System.out.println(meter + "." +
							// func.getText());
							// }
						}

					}
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return list;
	}

	public synchronized static int getID() {
		if (PacketId > 65535) {
			PacketId = 1;
		} else {
			PacketId = PacketId + 1;
		}
		return PacketId;
	}

	public static class Millisecond {
		public static final long SECOND_1 = 1000L;
		public static final long SECOND_3 = 1000L * 3;
		public static final long SECOND_10 = 1000L * 10;
		public static final long SECOND_20 = 1000L * 20;
		public static final long SECOND_30 = 1000L * 30;
		public static final long MINUTE_1 = 1000L * 60 * 1;
		public static final long MINUTE_3 = 1000L * 60 * 3;
		public static final long MINUTE_5 = 1000L * 60 * 5;
		public static final long MINUTE_10 = 1000L * 60 * 10;
		public static final long MINUTE_15 = 1000L * 60 * 15;
		public static final long MINUTE_30 = 1000L * 60 * 30;
		public static final long MINUTE_60 = 1000L * 60 * 60;
		public static final long MINUTE_1440 = 1000L * 60 * 60 * 24;
		public static final long HOUR = 1000L * 60 * 60;
		public static final long DAY = 1000L * 60 * 60 * 24;

	}
}
