package cn.escheduler.api.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.zookeeper.client.FourLetterWordMain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Scanner;

/**
 *	zookeeper状态监控:4字口诀 
 *
 */
public class ZooKeeperState {

	private static final Logger logger = LoggerFactory.getLogger(ZooKeeperState.class);

	private final String host;
	private final int port;

	private int minLatency = -1, avgLatency = -1, maxLatency = -1;
	private long received = -1;
	private long sent = -1;
	private int outStanding = -1;
	private long zxid = -1;
	private String mode = null;
	private int nodeCount = -1;
	private int watches = -1;
	private int connections = -1;

	public ZooKeeperState(String connectionString) {
		String host = connectionString.substring(0,
				connectionString.indexOf(':'));
		int port = Integer.parseInt(connectionString.substring(connectionString
				.indexOf(':') + 1));
		this.host = host;
		this.port = port;
	}

	public void getZookeeperInfo() {
		String content = cmd("srvr");
		if (StringUtils.isNotBlank(content)) {
			Scanner scannerForStat = new Scanner(content);
			while (scannerForStat.hasNext()) {
				String line = scannerForStat.nextLine();
				if (line.startsWith("Latency min/avg/max:")) {
					String[] latencys = getStringValueFromLine(line).split("/");
					minLatency = Integer.parseInt(latencys[0]);
					avgLatency = Integer.parseInt(latencys[1]);
					maxLatency = Integer.parseInt(latencys[2]);
				} else if (line.startsWith("Received:")) {
					received = Long.parseLong(getStringValueFromLine(line));
				} else if (line.startsWith("Sent:")) {
					sent = Long.parseLong(getStringValueFromLine(line));
				} else if (line.startsWith("Outstanding:")) {
					outStanding = Integer.parseInt(getStringValueFromLine(line));
				} else if (line.startsWith("Zxid:")) {
					zxid = Long.parseLong(getStringValueFromLine(line).substring(2), 16);
				} else if (line.startsWith("Mode:")) {
					mode = getStringValueFromLine(line);
				} else if (line.startsWith("Node count:")) {
					nodeCount = Integer.parseInt(getStringValueFromLine(line));
				}
			}
			scannerForStat.close();
		}

		String wchsText = cmd("wchs");
		if (StringUtils.isNotBlank(wchsText)) {
			Scanner scannerForWchs = new Scanner(wchsText);
			while (scannerForWchs.hasNext()) {
				String line = scannerForWchs.nextLine();
				if (line.startsWith("Total watches:")) {
					watches = Integer.parseInt(getStringValueFromLine(line));
				}
			}
			scannerForWchs.close();
		}
		
		String consText = cmd("cons");
		if (StringUtils.isNotBlank(consText)) {
			Scanner scannerForCons = new Scanner(consText);
			if (StringUtils.isNotBlank(consText)) {
				connections = 0;
			}
			while (scannerForCons.hasNext()) {
				@SuppressWarnings("unused")
				String line = scannerForCons.nextLine();
				++connections;
			}
			scannerForCons.close();
		}
	}


	public boolean ruok() {
		return "imok\n".equals(cmd("ruok"));
	}


	private String getStringValueFromLine(String line) {
		return line.substring(line.indexOf(":") + 1, line.length()).replaceAll(
				" ", "").trim();
	}

	private class SendThread extends Thread {
		private String cmd;

		public String ret = "";

		public SendThread(String cmd) {
			this.cmd = cmd;
		}

		@Override
		public void run() {
			try {
				ret = FourLetterWordMain.send4LetterWord(host, port, cmd);
			} catch (IOException e) {
				logger.error(e.getMessage(),e);
				return;
			}
		}

	}

	private String cmd(String cmd) {
		final int waitTimeout = 5;
		SendThread sendThread = new SendThread(cmd);
		sendThread.setName("FourLetterCmd:" + cmd);
		sendThread.start();
		try {
			sendThread.join(waitTimeout * 1000);
			return sendThread.ret;
		} catch (InterruptedException e) {
			logger.error("send " + cmd + " to server " + host + ":" + port + " failed!", e);
		}
		return "";
	}

	public Logger getLogger() {
		return logger;
	}

	public String getHost() {
		return host;
	}

	public int getPort() {
		return port;
	}

	public int getMinLatency() {
		return minLatency;
	}

	public int getAvgLatency() {
		return avgLatency;
	}

	public int getMaxLatency() {
		return maxLatency;
	}

	public long getReceived() {
		return received;
	}

	public long getSent() {
		return sent;
	}

	public int getOutStanding() {
		return outStanding;
	}

	public long getZxid() {
		return zxid;
	}

	public String getMode() {
		return mode;
	}

	public int getNodeCount() {
		return nodeCount;
	}

	public int getWatches() {
		return watches;
	}

	public int getConnections() {
		return connections;
	}

	@Override
	public String toString() {
		return "ZooKeeperState [host=" + host + ", port=" + port
				+ ", minLatency=" + minLatency + ", avgLatency=" + avgLatency
				+ ", maxLatency=" + maxLatency + ", received=" + received
				+ ", sent=" + sent + ", outStanding=" + outStanding + ", zxid="
				+ zxid + ", mode=" + mode + ", nodeCount=" + nodeCount
				+ ", watches=" + watches + ", connections="
				+ connections + "]";
	}
	
	
	
}
