package io.mycat.net2;

import java.io.IOException;
import java.net.StandardSocketOptions;
import java.nio.channels.NetworkChannel;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 存放当前所有连接的信息,包括客户端和服务端等,以及Network部分所使用共用对象
 *
 * @author wuzhih
 *
 */
public class NetSystem {
	private static final Logger LOGGER = LoggerFactory.getLogger(NetSystem.class);
	public static final int RUNNING = 0;
	public static final int SHUTING_DOWN = -1;
	// private static final Logger LOGGER = Logger.getLogger("NetSystem");
	private static NetSystem INSTANCE;
	private final SharedBufferPool bufferPool;
	// 用来执行那些耗时的任务
	private final NameableExecutor executor;
	// 用来执行定时任务
	private final NamebleScheduledExecutor timer;
	private final ConcurrentMap<Long, Connection> allConnections;
	private long netInBytes;
	private long netOutBytes;
	private SystemConfig netConfig;
	private NIOConnector connector;

	public static NetSystem getInstance() {
		return INSTANCE;
	}

	public NetSystem(SharedBufferPool bufferPool, NameableExecutor executor, NamebleScheduledExecutor timer)
			throws IOException {
		this.bufferPool = bufferPool;
		this.executor = executor;
		this.timer = timer;
		this.allConnections = new ConcurrentHashMap<Long, Connection>();
		INSTANCE = this;
	}

	public SharedBufferPool getBufferPool() {
		return bufferPool;
	}

	public NIOConnector getConnector() {
		return connector;
	}

	public void setConnector(NIOConnector connector) {
		this.connector = connector;
	}

	public int getWriteQueueSize() {
		int total = 0;
		for (Connection con : allConnections.values()) {
			total += con.getWriteQueue().size();
		}

		return total;

	}

	public SystemConfig getNetConfig() {
		return netConfig;
	}

	public void setNetConfig(SystemConfig netConfig) {
		this.netConfig = netConfig;
	}

	public NameableExecutor getExecutor() {
		return executor;
	}

	public NamebleScheduledExecutor getTimer() {
		return timer;
	}

	public long getNetInBytes() {
		return netInBytes;
	}

	public void addNetInBytes(long bytes) {
		netInBytes += bytes;
	}

	public long getNetOutBytes() {
		return netOutBytes;
	}

	public void addNetOutBytes(long bytes) {
		netOutBytes += bytes;
	}

	/**
	 * 添加一个连接到系统中被监控
	 *
	 * @param c
	 */
	public void addConnection(Connection c) {
		allConnections.put(c.getId(), c);
	}

	public ConcurrentMap<Long, Connection> getAllConnectios() {
		return allConnections;
	}

	/**
	 * 定时执行该方法,回收部分资源。
	 */
	public void checkConnections() {
		Iterator<Entry<Long, Connection>> it = allConnections.entrySet().iterator();
		while (it.hasNext()) {
			Connection c = it.next().getValue();

			// 删除空连接
			if (c == null) {
				it.remove();
				continue;
			}

			// 清理已关闭连接,否则空闲检查。
			if (c.isClosed()) {
				c.cleanup();
				it.remove();
			} else {
				c.idleCheck();
			}
		}
	}

	public void removeConnection(Connection con) {
		this.allConnections.remove(con.getId());

	}

	public void setSocketParams(Connection con, boolean isFrontChannel) throws IOException {
		int sorcvbuf = 0;
		int sosndbuf = 0;
		int soNoDelay = 0;
		if (isFrontChannel) {
			sorcvbuf = netConfig.getFrontsocketsorcvbuf();
			sosndbuf = netConfig.getFrontsocketsosndbuf();
			soNoDelay = netConfig.getFrontSocketNoDelay();
		} else {
			sorcvbuf = netConfig.getBacksocketsorcvbuf();
			sosndbuf = netConfig.getBacksocketsosndbuf();
			soNoDelay = netConfig.getBackSocketNoDelay();
		}
		NetworkChannel channel = con.getChannel();
		channel.setOption(StandardSocketOptions.SO_RCVBUF, sorcvbuf);
		channel.setOption(StandardSocketOptions.SO_SNDBUF, sosndbuf);
		channel.setOption(StandardSocketOptions.TCP_NODELAY, soNoDelay == 1);
		channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
		channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);

		con.setMaxPacketSize(netConfig.getMaxPacketSize());
		con.setPacketHeaderSize(netConfig.getPacketHeaderSize());

	}

}