package cn.mutils.app.queue;

import java.util.LinkedList;
import java.util.List;

import cn.mutils.app.event.ContextOwnerDispathcer;

@SuppressWarnings("rawtypes")
public class Queue extends ContextOwnerDispathcer implements IQueue, IQueueItemListener {

	protected boolean mRunInBackground = true;

	protected int mMaxRunningCount = 1;

	protected List<IQueueItem<?>> mQueue;

	protected List<IQueueItem<?>> mQueueToBe;

	protected void updateRunState() {
		boolean runningBackground = isRunningBackground();
		if (runningBackground != mRunInBackground) {
			mRunInBackground = runningBackground;
			for (IQueueListener listener : getListeners(IQueueListener.class)) {
				listener.onRunStateChanged(this);
			}
		}
	}

	@Override
	public boolean isRunInBackground() {
		return mRunInBackground;
	}

	protected boolean isRunningBackground() {
		if (mQueue == null || mQueueToBe == null) {
			return true;
		}
		for (IQueueItem<?> task : mQueue) {
			if (!task.isRunInBackground()) {
				return false;
			}
		}
		for (IQueueItem<?> task : mQueueToBe) {
			if (!task.isRunInBackground()) {
				return false;
			}
		}
		return true;
	}

	@Override
	public int getMaxRunningCount() {
		return mMaxRunningCount;
	}

	@Override
	public void setMaxRunningCount(int maxRunningCount) {
		mMaxRunningCount = maxRunningCount;
	}

	@Override
	public void add(IQueueItem<?> task) {
		synchronized (this) {
			if (mQueueToBe == null) {
				mQueueToBe = new LinkedList<IQueueItem<?>>();
			}
		}
		mQueueToBe.add(task);
		startOneItem();
	}

	protected void startOneItem() {
		if (mQueue != null && mQueue.size() >= mMaxRunningCount) {
			return;
		}
		if (mQueueToBe != null && mQueueToBe.size() == 0) {
			return;
		}
		IQueueItem<?> task = mQueueToBe.remove(0);
		synchronized (this) {
			if (mQueue == null) {
				mQueue = new LinkedList<IQueueItem<?>>();
			}
		}
		mQueue.add(task);
		task.addListener(this);
		task.setContext(mContext);
		task.start();
	}

	@Override
	public void clear() {
		if (mQueue != null) {
			for (IQueueItem<?> task : mQueue) {
				task.removeListener(this);
				task.stop();
			}
			mQueue.clear();
		}
		if (mQueueToBe != null) {
			for (IQueueItem<?> task : mQueueToBe) {
				task.removeListener(this);
				task.stop();
			}
			mQueueToBe.clear();
		}
	}

	@Override
	public void onException(IQueueItem task, Exception e) {

	}

	@Override
	public void onStart(IQueueItem task) {
		if (mQueue == null) {
			return;
		}
		if (!mQueue.contains(task)) {
			return;
		}
		onItemStart(task);
		updateRunState();
	}

	@Override
	public void onStop(IQueueItem task) {
		boolean isInQueueToBe = false;
		boolean isInQueue = mQueue != null && mQueue.contains(task);
		if (!isInQueue) {
			isInQueueToBe = mQueueToBe != null && mQueueToBe.contains(task);
		}
		if (!isInQueue && !isInQueueToBe) {
			return;
		}
		if (isInQueue) {
			mQueue.remove(task);
		} else {
			mQueueToBe.remove(task);
		}
		onItemStop(task);
		startOneItem();
		updateRunState();
	}

	protected void onItemStart(IQueueItem<?> task) {

	}

	protected void onItemStop(IQueueItem<?> task) {

	}

}

@@ -1364,16 +1364,56 @@
 task) %7B%0A
+%09%09if (task.isStoped()) %7B%0A%09%09%09return;%0A%09%09%7D%0A
 %09%09synchr
@@ -1532,32 +1532,58 @@
 ToBe.add(task);%0A
+%09%09task.addListener(this);%0A
 %09%09startOneItem()
@@ -1939,34 +1939,8 @@
 k);%0A
-%09%09task.addListener(this);%0A
 %09%09ta

Fix bug for queue running state while task who is added to queue is stoped by outside but it has not been started by queue.