package com.xxl.job.admin.util;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooDefs.Perms;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

public class ZookeeperClientUtil {
	private static Logger logger = LoggerFactory.getLogger(ZookeeperClientUtil.class);

	private ZooKeeper zk;
	// zookeeper地址
	private static String servers;
	// 链接超时时间
	private int sessionTimeout = 60000;

	public static String mainPath;

	public static void init(String serversAddress, String mainPathStr) {
		servers = serversAddress;
		mainPath = mainPathStr;
	}

	public ZooKeeper getAliveZk() {
		ZooKeeper aliveZk = zk;
		if (aliveZk != null && aliveZk.getState().isAlive()) {
			return aliveZk;
		} else {
			zkReconnect();
			return zk;
		}
	}

	public synchronized void zkReconnect() {
		close();
		try {
			connect();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public synchronized void close() {
		if (zk != null) {
			try {
				zk.close();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			zk = null;
		}
	}

	public void mkPaths(String path) throws KeeperException, InterruptedException {
		String[] subs = path.split("\\/");
		if (subs.length < 2) {
			return;
		}
		String curPath = "";
		for (int i = 1; i < subs.length; i++) {
			curPath = curPath + "/" + subs[i];
			Stat stat = getAliveZk().exists(curPath, false);
			if (stat == null) {
				getAliveZk().create(path, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
			}
		}
	}

	private synchronized void connect() throws IOException {
		if (zk == null && !StringUtils.isEmpty(servers))
			zk = new ZooKeeper(servers, sessionTimeout, null);
	}

	public String getData(String path) {
		String result = null;
		try {
			byte[] data = getAliveZk().getData(path, Boolean.TRUE, null);
			if (null != data) {
				result = new String(data, "UTF-8");
			}
		} catch (KeeperException e) {
			logger.error("获取节点发送错误,path=" + path + " errmsg=" + e.getMessage());
		} catch (InterruptedException e) {
			logger.error("获取节点发送错误,path=" + path + " errmsg=" + e.getMessage());
		} catch (Exception e) {
			logger.error("获取子节点发送错误,mainPath=" + mainPath + " errmsg=" + e.getMessage());
		}
		return result;
	}

	public void setData(String path, String dataStr) {

		try {
			Stat stat = getAliveZk().exists(path, false);
			if (stat == null) {
				getAliveZk().create(path, null, Collections.singletonList(new ACL(Perms.ALL, Ids.ANYONE_ID_UNSAFE)),
						CreateMode.PERSISTENT);
			}
			getAliveZk().setData(path, dataStr.getBytes(), -1);

		} catch (KeeperException e) {
			logger.error("获取节点发送错误,path=" + path, e);
		} catch (InterruptedException e) {
			logger.error("获取节点发送错误,path=" + path, e);
		} catch (Exception e) {
			logger.error("获取子节点发送错误,mainPath=" + mainPath, e);
		}
	}

	public List<String> getChildren() {
		List<String> data = null;
		try {
			data = getAliveZk().getChildren(mainPath, Boolean.FALSE);
		} catch (KeeperException e) {
			logger.error("获取子节点发送错误,mainPath=" + mainPath, e);
		} catch (InterruptedException e) {
			logger.error("获取子节点发送错误,mainPath=" + mainPath, e);
		} catch (Exception e) {
			logger.error("获取子节点发送错误,mainPath=" + mainPath, e);
		}
		return data;
	}

	public void setSessionTimeout(int sessionTimeout) {
		this.sessionTimeout = sessionTimeout;
	}

}
