package com.saga.main;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.hadoop.conf.Configuration;
import org.zillion.util.log.LogUtil;

import com.persagy.communication.mina.tcp.server.TCPServerManager;
import com.persagy.communication.mina.udp.server.UDPServerManager;
import com.persagy.communication.util.IServerManager;
import com.saga.thread.common.CheckThread;
import com.saga.thread.common.LoadConfigThread;
import com.saga.thread.common.SaveThread;
import com.saga.thread.common.StatsThread;
import com.saga.thread.common.WTDBThread;
import com.saga.thread.down.CollectThread;
import com.saga.thread.up.SendThread;
import com.saga.util.Constant;
import com.saga.util.HBaseUtil;
import com.zillion.database.agent.ZillionAgent;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		// 初始化
		init(args);
		// 业务进程启动
		threadStart();
	}

	private static void threadStart() {
		// TODO Auto-generated method stub
		// 点位状态监控
		try {
			new CheckThread(Constant.agent).start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			LogUtil.error("Main.CheckThread: " + e.toString());
		}
		// 配置实时加载进程
		try {
			new LoadConfigThread().start();
			Thread.sleep(3L);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			LogUtil.error("Main.LoadConfigThread: " + e.toString());
		}
		// 采集进程
		try {
			String ports = Constant.TypePort.get("Down");
			new CollectThread(Integer.valueOf(ports)).start();
			// for (String p : ports.split(",")) {
			// new CollectThread(Integer.valueOf(p)).start();
			// }

			Thread.sleep(3L);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			LogUtil.error("Main.CollectThread: " + e.toString());
		}
		// 上传进程
		List<IServerManager> udpserverList = new ArrayList<IServerManager>();
		List<IServerManager> tcpserverList = new ArrayList<IServerManager>();
		udpserverList.add(new UDPServerManager("0.0.0.0", Integer.valueOf(Constant.TypePort.get("Up")), "utf-8", 1000));
		tcpserverList.add(new TCPServerManager("0.0.0.0", Integer.valueOf(Constant.TypePort.get("Up")), "utf-8", 1000));

		for (IServerManager server : udpserverList) {
			new SendThread(server).start();
			try {
				Thread.sleep(3L);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				LogUtil.error("Main.SendThread: " + e.toString());
			}
		}
		for (IServerManager server : tcpserverList) {
			new SendThread(server).start();
			try {
				Thread.sleep(3L);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				LogUtil.error("Main.SendThread: " + e.toString());
			}
		}
		// 数据处理进程
		try {
			new SaveThread().start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			LogUtil.error("Main.SaveThread: " + e.toString());
		}
		// 数据写库进程
		try {
			List<WTDBThread> wtdbthreadList = new ArrayList<WTDBThread>();
			for (int i = 0; i < Constant.InsertThread; i++) {
				WTDBThread thread = new WTDBThread(Constant.agent);
				thread.start();
				wtdbthreadList.add(thread);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			LogUtil.error("Main.WTDBThread: " + e.toString());
		}

		// 统计进程
		try {
			new StatsThread().start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			LogUtil.error("Main.StatsThread: " + e.toString());
		}
	}

	private static void init(String[] args) {
		// TODO Auto-generated method stub
		try {
			// ZillionAgent 启动
			agentStart(args);
			// 初始化数据库环境
			initDB();
			// 加载DB配置
			loadDB();
			//// 加载Config文件配置
			// loadFileConfig();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			LogUtil.error("Main.init: " + e.toString());
			System.exit(0);
		}
	}

	// private static void loadFileConfig() {
	// // TODO Auto-generated method stub
	// // 加载采集器配置文件
	// // 文件夹命名格式：config+"-"+楼号+"-"+mac序号，示例：config-1101080002-1
	// Constant.getConfigFile(LogUtil.GetPath(), "config-", "port");
	// // 采集器点位位置信息写入数据库
	// for (Entry<String, String> pi : Constant.pointInfo.entrySet()) {
	// String building = pi.getKey().split("-")[0];
	// String mac = pi.getKey().split("-")[1];
	// String node = mac;
	// String point = pi.getKey().split("-")[2];
	// String busno = pi.getValue().split("-")[0];
	// String site = pi.getValue().split("-")[1];
	// try {
	// HBaseUtil.InsertPointInfo(Constant.agent,
	// Constant.BuildingDB.get(building), building, node, point,
	// busno, site);
	// } catch (Exception e) {
	// // TODO Auto-generated catch block
	// e.printStackTrace();
	// }
	// // System.out.println(building + node + point + busno + site);
	// }
	// }

	private static void loadDB() {
		// TODO Auto-generated method stub
		// // V1.0点位日志结构
		// {
		// loadStatus();
		// }
		// V2.0点位日志结构
		{
			// 先加载状态再加载列表，如无状态记录则根据列表生成null
			loadStatus2();
			loadPointList2();

		}

	}

	private static void loadPointList2() {
		// TODO Auto-generated method stub
		// 重新启动加载点位列表
		for (Entry<String, String> bd : Constant.BuildingDB.entrySet()) {
			try {
				String project = bd.getKey();
				String db = bd.getValue();
				HBaseUtil.LoadDB2Cache_dy_pointlist(Constant.agent, db, "dy_pointlist", project);

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				LogUtil.error("Main.loadPointList2: " + e.toString());
			}
		}
	}

//	private static void loadStatus() {
//		// TODO Auto-generated method stub
//		// 重新启动加载节点、点位状态
//		for (Entry<String, String> bd : Constant.BuildingDB.entrySet()) {
//			try {
//				String project = bd.getKey();
//				String db = bd.getValue();
//				HBaseUtil.GetCollectorStatus(Constant.agent, db, "pointgatewaystatus", project);
//				HBaseUtil.GetPointStatus(Constant.agent, db, "pointstatus", project);
//			} catch (Exception e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//				LogUtil.error("Main.loadStatus: " + e.toString());
//			}
//		}
//	}

	private static void loadStatus2() {
		// TODO Auto-generated method stub
		// 重新启动加载节点、点位状态
		for (Entry<String, String> bd : Constant.BuildingDB.entrySet()) {
			try {
				String project = bd.getKey();
				String db = bd.getValue();
				HBaseUtil.LoadDB2Cache_ps_physical_status(Constant.agent, db, "ps_physical_status", project);
				HBaseUtil.LoadDB2Cache_ps_virtual_meter_status(Constant.agent, db, "ps_virtual_meter_status", project);
				HBaseUtil.LoadDB2Cache_ps_virtual_point_status(Constant.agent, db, "ps_virtual_point_status", project);
				HBaseUtil.LoadDB2Cache_ps_virtual_project_status(Constant.agent, db, "ps_virtual_project_status",
						project);

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				LogUtil.error("Main.loadStatus2: " + e.toString());
			}
		}
	}

	private static void initDB() {
		// TODO Auto-generated method stub
		Map<String, String> dbList = new HashMap<String, String>();
		for (Entry<String, String> bd : Constant.BuildingDB.entrySet()) {
			dbList.put(bd.getValue(), bd.getValue());
		}

		for (String db : dbList.keySet()) {
			try {

				createDB(db);

				// // V1.0点位日志结构
				// {
				// Thread.sleep(Constant.Millisecond.SECOND_1);
				// // dropTB(db);
				// // Thread.sleep(Constant.Millisecond.SECOND_1);
				// createTB(db);
				// }

				// V2.0点位日志结构
				{
					// dropTB2(db);
					// Thread.sleep(Constant.Millisecond.SECOND_1);
					createTB2(db);
				}

				Thread.sleep(Constant.Millisecond.SECOND_1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();

			}
		}
	}

	private static void createTB2(String db) {
		// TODO Auto-generated method stub
		try {
			HBaseUtil.CreateTable(Constant.agent, db, "original_month");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_present(Constant.agent, db, "original_present");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_set(Constant.agent, db, "originalset");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_setpresent(Constant.agent, db, "originalset_present");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			// dy_pointlist
			HBaseUtil.CreateTable_dy_pointlist(Constant.agent, db, "dy_pointlist");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			// fjd_0_buildingcomputetime
			HBaseUtil.CreateTable_fjd_0_buildingcomputetime(Constant.agent, db, "fjd_0_buildingcomputetime");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_physical_status
			HBaseUtil.CreateTable_ps_physical_status(Constant.agent, db, "ps_physical_status");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_physical_log
			HBaseUtil.CreateTable_ps_physical_log(Constant.agent, db, "ps_physical_log");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_point_status
			HBaseUtil.CreateTable_ps_virtual_point_status(Constant.agent, db, "ps_virtual_point_status");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_point_log
			HBaseUtil.CreateTable_ps_virtual_point_log(Constant.agent, db, "ps_virtual_point_log");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_meter_status
			HBaseUtil.CreateTable_ps_virtual_meter_status(Constant.agent, db, "ps_virtual_meter_status");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_meter_log
			HBaseUtil.CreateTable_ps_virtual_meter_log(Constant.agent, db, "ps_virtual_meter_log");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_project_status
			HBaseUtil.CreateTable_ps_virtual_project_status(Constant.agent, db, "ps_virtual_project_status");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_project_log
			HBaseUtil.CreateTable_ps_virtual_project_log(Constant.agent, db, "ps_virtual_project_log");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			Thread.sleep(Constant.Millisecond.SECOND_30);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void dropTB2(String db) {
		// TODO Auto-generated method stub
		try {
			// Constant.agent.DDL_DropTable(db, "original_month");
			// Thread.sleep(Constant.Millisecond.SECOND_3);
			// Constant.agent.DDL_DropTable(db, "original_present");
			// Thread.sleep(Constant.Millisecond.SECOND_3);
			// Constant.agent.DDL_DropTable(db, "originalset");
			// Thread.sleep(Constant.Millisecond.SECOND_3);
			// Constant.agent.DDL_DropTable(db, "originalset_present");
			// Thread.sleep(Constant.Millisecond.SECOND_3);
			// // dy_pointlist
			// Constant.agent.DDL_DropTable(db, "dy_pointlist");
			// Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_physical_status
			Constant.agent.DDL_DropTable(db, "ps_physical_status");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_physical_log
			Constant.agent.DDL_DropTable(db, "ps_physical_log");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_point_status
			Constant.agent.DDL_DropTable(db, "ps_virtual_point_status");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_point_log
			Constant.agent.DDL_DropTable(db, "ps_virtual_point_log");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_meter_status
			Constant.agent.DDL_DropTable(db, "ps_virtual_meter_status");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_meter_log
			Constant.agent.DDL_DropTable(db, "ps_virtual_meter_log");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_project_status
			Constant.agent.DDL_DropTable(db, "ps_virtual_project_status");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			// ps_virtual_project_log
			Constant.agent.DDL_DropTable(db, "ps_virtual_project_log");
			Thread.sleep(Constant.Millisecond.SECOND_3);

			Thread.sleep(Constant.Millisecond.SECOND_30);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void createTB(String db) {
		// TODO Auto-generated method stub
		try {
			HBaseUtil.CreateTable(Constant.agent, db, "original_month");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_present(Constant.agent, db, "original_present");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_set(Constant.agent, db, "originalset");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_setpresent(Constant.agent, db, "originalset_present");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_CollectorStatus(Constant.agent, db, "pointgatewaystatus");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_CollectorCommunicationLog(Constant.agent, db, "pointgatewaylog");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_PointStatus(Constant.agent, db, "pointstatus");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_PointCommunicationLog(Constant.agent, db, "pointlog");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			HBaseUtil.CreateTable_PointInfo(Constant.agent, db, "pointinfo");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void dropTB(String db) {
		// TODO Auto-generated method stub
		try {
			// Constant.agent.DDL_DropTable(db, "original_month");
			// Thread.sleep(Constant.Millisecond.SECOND_3);
			// Constant.agent.DDL_DropTable(db, "original_present");
			// Thread.sleep(Constant.Millisecond.SECOND_3);
			// Constant.agent.DDL_DropTable(db, "originalset");
			// Thread.sleep(Constant.Millisecond.SECOND_3);
			// Constant.agent.DDL_DropTable(db, "originalset_present");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			Constant.agent.DDL_DropTable(db, "collectorstatus");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			Constant.agent.DDL_DropTable(db, "collectorcommunicationlog");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			Constant.agent.DDL_DropTable(db, "pointstatus");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			Constant.agent.DDL_DropTable(db, "pointcommunicationlog");
			Thread.sleep(Constant.Millisecond.SECOND_3);
			Constant.agent.DDL_DropTable(db, "pointinfo");
			Thread.sleep(Constant.Millisecond.SECOND_30);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void createDB(String db) {
		// TODO Auto-generated method stub
		try {
			HBaseUtil.CreateDB(Constant.agent, db);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void agentStart(String[] args) {
		// TODO Auto-generated method stub
		try {
			String resource = "/hbase-site.xml";
			Configuration configuration = new Configuration();

			configuration.addResource(new FileInputStream(System.getProperty("user.dir") + resource));
			String zookeeper_connectionAddress = "zookeeper1:2181,zookeeper2:2181,zookeeper3:2181";

			if (args != null && args.length > 0 && "test".equalsIgnoreCase(args[0])) {
				// zookeeper_connectionAddress =
				// "zk01.td.com:2181,zk02.td.com:2181,zk03.td.com:2181";
				zookeeper_connectionAddress = "zookeeper1,zookeeper2,zookeeper3";
			}

			int zookeeper_sessionTimeout = 300000;
			Constant.agent = new ZillionAgent(configuration, zookeeper_connectionAddress, zookeeper_sessionTimeout);

			Constant.agent.Start();
			// LogUtil.info("" + Constant.BuildingDB);
			// LogUtil.info("" + Constant.BuildingAdds);
			// LogUtil.info("" + Constant.BuildingConv);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			LogUtil.error("Main.init.agentStart: " + e.toString());
		}
	}

}
