package com.chenyang.nse.bussiness.init;

import com.chenyang.nse.bussiness.config.PropertiesLoaderUtils;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreServerInfoStatus;
import com.chenyang.nse.bussiness.entity.orm.table.core.desensitizationtask.Desensitizationtask;
import com.chenyang.nse.bussiness.entity.vo.TCoreServerInfoStatusVo;
import com.chenyang.nse.bussiness.service.core.DesensitizationtaskService;
import com.chenyang.nse.bussiness.service.core.ServerInfoStatusService;
import com.chenyang.nse.bussiness.tools.ha.HaInfo;
import com.chenyang.nse.bussiness.tools.ha.TcpServer;
import com.chenyang.nse.bussiness.tools.ha.TcpSynTool;
import com.chenyang.nse.bussiness.tools.net.IpAddressTool;
import java.io.IOException;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

public class HighAvailabilityInitListener implements ApplicationListener<ContextRefreshedEvent> {
   private static Logger logger = LoggerFactory.getLogger(HighAvailabilityInitListener.class);
   @Autowired
   private ServerInfoStatusService serverInfoStatusService;
   @Autowired
   private DesensitizationtaskService desensitizationtaskService;
   private int cnt = 0;

   public void onApplicationEvent(ContextRefreshedEvent arg0) {
      Properties props = new Properties();

      try {
         props = PropertiesLoaderUtils.loadAllProperties("config.properties");
      } catch (IOException e) {
         e.printStackTrace();
      }

      String isHaServer = props.getProperty("ha_is_ha_server");
      if ("1".equals(isHaServer)) {
         if (arg0.getApplicationContext().getParent() == null) {
            System.out.println(">>>>>>>>>>>>>>>>>>>>HighAvailabilityInitListener start>>>>>>>>>>>>>>>>>>>>");
            ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
            executorService.scheduleAtFixedRate(new Runnable() {
               public void run() {
                  Date curDate = new Date();
                  new Properties();

                  try {
                     try {
                        Properties props = PropertiesLoaderUtils.loadAllProperties("config.properties");
                        String connTcpTimes = props.getProperty("ha_conn_tcp_times");
                        String curServerIp = (String)IpAddressTool.getLinuxLocalIp().get(0);
                        String curServerPort = props.getProperty("ha_curserver_port");
                        TCoreServerInfoStatusVo cond = new TCoreServerInfoStatusVo();
                        cond.setIp(curServerIp);
                        cond.setPort(curServerPort);
                        String conStatus = "0";
                        if (0 == HighAvailabilityInitListener.this.cnt) {
                           HaInfo.isPrimaryServer = "0";
                           String isActive = "1";
                           List<TCoreServerInfoStatus> tcsisLst = HighAvailabilityInitListener.this.serverInfoStatusService.queryPrimaryServer();
                           if (null != tcsisLst && tcsisLst.size() > 0) {
                              TCoreServerInfoStatus primarySisInfo = (TCoreServerInfoStatus)tcsisLst.get(0);
                              if (curServerIp.equals(primarySisInfo.getIp()) && curServerPort.equals(primarySisInfo.getPort())) {
                                 HaInfo.isPrimaryServer = "1";
                              } else {
                                 HaInfo.primarySisInfo = primarySisInfo;
                              }
                           }

                           List<TCoreServerInfoStatus> curLst = HighAvailabilityInitListener.this.serverInfoStatusService.queryServerByCondition(cond);
                           if (null != curLst && curLst.size() > 0) {
                              TCoreServerInfoStatus curSisInfo = (TCoreServerInfoStatus)curLst.get(0);
                              curSisInfo.setIsprimaryserver(HaInfo.isPrimaryServer);
                              curSisInfo.setIsactive(isActive);
                              curSisInfo.setStarttime(curDate);
                              HighAvailabilityInitListener.this.serverInfoStatusService.updateServerInfoStatus(curSisInfo);
                              HaInfo.isExist = "1";
                              System.out.println("IP:" + cond.getIp() + "服务器启动时，集群中已存在主服务，当前服务器被设置为子服务..");
                           }

                           HighAvailabilityInitListener.this.cnt++;
                        } else {
                           List<TCoreServerInfoStatus> curLst = HighAvailabilityInitListener.this.serverInfoStatusService.queryServerByCondition(cond);
                           if (null != curLst && curLst.size() > 0) {
                              if ("0".equals(HaInfo.isExist)) {
                                 TCoreServerInfoStatus curSisInfo = (TCoreServerInfoStatus)curLst.get(0);
                                 curSisInfo.setIsprimaryserver(HaInfo.isPrimaryServer);
                                 curSisInfo.setIsactive("1");
                                 curSisInfo.setStarttime(curDate);
                                 HighAvailabilityInitListener.this.serverInfoStatusService.updateServerInfoStatus(curSisInfo);
                                 HaInfo.isExist = "1";
                                 System.out.println("IP:" + cond.getIp() + "服务器已加入到集群中..");
                              }

                              List<TCoreServerInfoStatus> tcsisLst = HighAvailabilityInitListener.this.serverInfoStatusService.queryPrimaryServer();
                              if (null != tcsisLst && tcsisLst.size() > 0) {
                                 TCoreServerInfoStatus newPrimaryServerInfo = (TCoreServerInfoStatus)tcsisLst.get(0);
                                 HaInfo.primarySisInfo = newPrimaryServerInfo;
                                 if (curServerIp.equals(newPrimaryServerInfo.getIp()) && curServerPort.equals(newPrimaryServerInfo.getPort())) {
                                    HaInfo.isPrimaryServer = "1";
                                 } else {
                                    HaInfo.isPrimaryServer = "0";
                                 }

                                 if ("0".equals(HaInfo.isPrimaryServer)) {
                                    conStatus = HighAvailabilityInitListener.getConnectStatus(HaInfo.primarySisInfo.getIp(), new Integer(HaInfo.primarySisInfo.getPort()), new Integer(connTcpTimes));
                                    if ("0".equals(conStatus)) {
                                       List<TCoreServerInfoStatus> nextPServerLst = HighAvailabilityInitListener.this.serverInfoStatusService.queryNextPrimaryServer(HaInfo.primarySisInfo.getId());
                                       if (null != nextPServerLst && nextPServerLst.size() > 0) {
                                          TCoreServerInfoStatus nextPSInfo = (TCoreServerInfoStatus)nextPServerLst.get(0);
                                          if (curServerIp.equals(nextPSInfo.getIp()) && curServerPort.equals(nextPSInfo.getPort())) {
                                             HaInfo.isPrimaryServer = "1";
                                             nextPSInfo.setIsprimaryserver("1");
                                             HighAvailabilityInitListener.this.serverInfoStatusService.updateServerInfoStatus(nextPSInfo);
                                             HaInfo.primarySisInfo.setIsprimaryserver("0");
                                             HaInfo.primarySisInfo.setIsactive("0");
                                             HighAvailabilityInitListener.this.serverInfoStatusService.updateServerInfoStatus(HaInfo.primarySisInfo);
                                             System.out.println("IP:" + cond.getIp() + "服务器已自动切换为主服务器..");
                                          }

                                          HaInfo.primarySisInfo = nextPSInfo;
                                       }
                                    }
                                 } else {
                                    List<TCoreServerInfoStatus> allNotPServerLst = HighAvailabilityInitListener.this.serverInfoStatusService.queryAllNoPrimaryServer();

                                    for(int i = 0; i < allNotPServerLst.size(); ++i) {
                                       TCoreServerInfoStatus standbyServerInfo = (TCoreServerInfoStatus)allNotPServerLst.get(i);
                                       String standbyConStatus = HighAvailabilityInitListener.getConnectStatus(standbyServerInfo.getIp(), new Integer(standbyServerInfo.getPort()), new Integer(connTcpTimes));
                                       if ("0".equals(standbyConStatus)) {
                                          standbyServerInfo.setIsactive("0");
                                          HighAvailabilityInitListener.this.serverInfoStatusService.updateServerInfoStatus(standbyServerInfo);
                                       }
                                    }
                                 }
                              }
                           } else {
                              HaInfo.isExist = "0";
                              HaInfo.isPrimaryServer = "0";
                           }
                        }
                     } catch (Exception e) {
                        e.printStackTrace();
                     }

                  } finally {
                     ;
                  }
               }
            }, 0L, 10000L, TimeUnit.MILLISECONDS);
            System.out.println(">>>>>>>>>>>>>>>>>>>>TCP listen start>>>>>>>>>>>>>>>>>>>>");
            String resSynTcpServerPort = props.getProperty("ha_resources_syn_tcp_server_port");
            TcpServer server = new TcpServer(new Integer(resSynTcpServerPort));
            server.start();
            ScheduledExecutorService executorServiceTcp = Executors.newSingleThreadScheduledExecutor();
            executorServiceTcp.scheduleAtFixedRate(new Runnable() {
               public void run() {
                  if ("1".equals(HaInfo.isPrimaryServer) && "1".equals(HaInfo.isExist)) {
                     try {
                        List<Desensitizationtask> list = HighAvailabilityInitListener.this.desensitizationtaskService.queryEngineTaskAll();
                        List<Desensitizationtask> needSynlist = new ArrayList();

                        for(Desensitizationtask desensitizationtask : list) {
                           if (!"1".equals(desensitizationtask.getIsSynXml()) && "2".equals(desensitizationtask.getSave_state())) {
                              needSynlist.add(desensitizationtask);
                           }
                        }

                        for(int i = 0; i < needSynlist.size(); ++i) {
                           Desensitizationtask needSynTask = (Desensitizationtask)needSynlist.get(0);
                           String reStr = TcpSynTool.synchronizationXmlFile(needSynTask.getTasknamereal(), "0");
                           if ("1".equals(reStr)) {
                              Desensitizationtask desInfo = HighAvailabilityInitListener.this.desensitizationtaskService.queryTaskById(needSynTask.getId());
                              desInfo.setIsSynXml("1");
                              HighAvailabilityInitListener.this.desensitizationtaskService.updateTask(desInfo);
                           }
                        }
                     } catch (Exception e) {
                        e.printStackTrace();
                     } finally {
                        ;
                     }
                  }

               }
            }, 0L, 30000L, TimeUnit.MILLISECONDS);
         }

      }
   }

   public void addServerInfo(String curServerIp, String curServerPort, String isprimaryserver, String isActive) {
      TCoreServerInfoStatus tCoreServerInfoStatus = new TCoreServerInfoStatus();
      Date curDate = new Date();
      SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
      String systemAutoCreateName = "_server_" + df.format(curDate);
      if (StringUtils.isNotBlank(curServerIp)) {
         systemAutoCreateName = curServerIp.substring(curServerIp.lastIndexOf(".")) + systemAutoCreateName;
      }

      tCoreServerInfoStatus.setServername(systemAutoCreateName);
      tCoreServerInfoStatus.setIp(curServerIp);
      tCoreServerInfoStatus.setPort(curServerPort);
      tCoreServerInfoStatus.setIsprimaryserver(isprimaryserver);
      tCoreServerInfoStatus.setStarttime(curDate);
      tCoreServerInfoStatus.setIsactive(isActive);
      tCoreServerInfoStatus.setCreatetime(curDate);
      tCoreServerInfoStatus.setUpdatetime(curDate);
      tCoreServerInfoStatus.setDelflg("0");
      this.serverInfoStatusService.addServerInfoStatus(tCoreServerInfoStatus);
   }

   public static String getConnectStatus(String ip, int port, int times) {
      String conStatus = "0";

      for(int i = 0; i < times; ++i) {
         String conFlg = getConnectStatusByTcp(ip, port);
         if ("1".equals(conFlg)) {
            conStatus = "1";
            break;
         }
      }

      return conStatus;
   }

   public static String getConnectStatusByTcp(String ip, int port) {
      Properties props = new Properties();
      try {
         props = PropertiesLoaderUtils.loadAllProperties("config.properties");
      } catch (IOException e) {
         e.printStackTrace();
      }
      String waitTime = props.getProperty("ha_tcp_wait_time");
      String conStatus = "0";
      Socket socket = new Socket();
      long startTimer = System.currentTimeMillis();
      try {
         SocketAddress address = new InetSocketAddress(ip, port);
         socket.connect(address, (new Integer(waitTime)).intValue());
         conStatus = "1";
         return conStatus;
      } catch (Exception exception) {
         return conStatus;
      } finally {
         Exception exception = null;
         long endTimer = System.currentTimeMillis();
         long connUseTime = endTimer - startTimer;
         String connStatus = "Failure";
         if ("1".equals(conStatus))
            connStatus = "Successful";
         String hostIp = "";
         try {
            hostIp = InetAddress.getLocalHost().getHostAddress();
         } catch (UnknownHostException e) {
            e.printStackTrace();
         }
         if ("0".equals(conStatus))
            logger.info(hostIp + " conn ip:" + ip + " port:" + port + " server use second is " + connUseTime + "ms ,conn stauts is " + connStatus);
      }
   }

   public static void main(String[] args) {
      String conStatus = getConnectStatusByTcp("192.168.2.106", 8081);
      System.out.println(">>>>>>>>>>>>>>conStatus is :" + conStatus);
   }

   private class ShutdownHook implements Runnable {
      public void run() {
         System.out.println("当前服务关闭中====start======");
         new Properties();

         try {
            Properties props = PropertiesLoaderUtils.loadAllProperties("config.properties");
            String curServerIp = (String)IpAddressTool.getLinuxLocalIp().get(0);
            String curServerPort = props.getProperty("ha_curserver_port");
            TCoreServerInfoStatusVo cond = new TCoreServerInfoStatusVo();
            cond.setIp(curServerIp);
            cond.setPort(curServerPort);
            List<TCoreServerInfoStatus> curLst = HighAvailabilityInitListener.this.serverInfoStatusService.queryServerByCondition(cond);
            if (null != curLst && curLst.size() > 0) {
               TCoreServerInfoStatus curSisInfo = (TCoreServerInfoStatus)curLst.get(0);
               curSisInfo.setIsactive("0");
               HighAvailabilityInitListener.this.serverInfoStatusService.updateServerInfoStatus(curSisInfo);
               HaInfo.isExist = "1";
            }

            System.out.println("当前服务关闭中====end======");
         } catch (Exception e) {
            e.printStackTrace();
         }

      }
   }
}
