package taurus.client;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

import com.taurus.core.util.ICallback;



/**
 * 网络(读/写) 线程管理
 * @author daixiwei	daixiwei15@126.com
 *
 */
public class ThreadManager {
	class MessgaeThread {
		public ICallback<Message>	_dataDelegate;

		public Message			_message;
	}
	
	private boolean					_running			= false;
	private Thread					_outThread;
	private boolean					_outHasQueuedItems	= false;
	private Queue<MessgaeThread>	_outThreadQueue		= new LinkedList<MessgaeThread>();
	private Object					_outQueueLocker		= new Object();
	private Stack<MessgaeThread> pool = new Stack<MessgaeThread>();

	private MessgaeThread MessgaeThreadGet() {
		if (pool.size() > 0) {
			MessgaeThread msg = pool.pop();
			return msg;
		} else
			return new MessgaeThread();
	}

	private void MessgaeThreadReturn(MessgaeThread value) {
		pool.push(value);
		value._dataDelegate = null;
		value._message = null;
	}

	private static void sleep(int ms) {
		try {
			Thread.sleep(ms);
		} catch (InterruptedException e) {
			
		}
	}

	private void outThread() {
		while (_running) {
			sleep(5);
			if (_outHasQueuedItems) {
				Object obj = _outQueueLocker;
				synchronized (obj) {
					while (_outThreadQueue.size() > 0) {
						MessgaeThread item = _outThreadQueue.poll();
						processOutItem(item);
					}
					_outHasQueuedItems = false;
				}
			}
		}
	}

	private void processOutItem(MessgaeThread item) {
		ICallback<Message> _dataDelegate = item._dataDelegate;
		Message message = item._message;
		MessgaeThreadReturn(item);
		if (_dataDelegate != null) {
			_dataDelegate.action(message);
		}
	}

	public void start() {
		if (_running) {
			return;
		}
		_running = true;
		if (_outThread == null) {
			_outThread = new Thread(new Runnable() {
				@Override
				public void run() {
					outThread();
				}
			});
			_outThread.start();
			_outThread.setName("WriteMessage");
		}
	}

	public void stop() {
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				stopThread();
			}
		});
		thread.start();
	}

	private void stopThread() {
		_running = false;

		if (_outThread != null) {
			_outThread.interrupt();
		}
		_outThread = null;
	}

	public void enqueueSend(ICallback<Message> callback, Message message) {
		MessgaeThread hashtable = MessgaeThreadGet();
		hashtable._dataDelegate = callback;
		hashtable._message = message;
		Object obj = _outQueueLocker;
		synchronized (obj) {
			_outThreadQueue.offer(hashtable);
			_outHasQueuedItems = true;
		}
	}
}
