// ProtocolActionQueue.cs
//
//  Copyright (C) 2008 Christian Eide
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using bareFTP.Protocol;

namespace bareFTP.Connection
{
	
	public class ProtocolActionQueue
	{
		//private Queue transferq;
		private List<IProtocolAction> tq;
		private Thread threadxfer;
		private Connection conn;
		
		public event EventHandler QueueEmpty;

		public virtual void OnQueueEmpty()
		{
			QueueEmpty(this, new EventArgs());
		}
		
		public ProtocolActionQueue(Connection conn)
		{
			this.conn = conn;
			//transferq = new Queue();
			tq = new List<IProtocolAction>();
			threadxfer = new Thread(DoAction);
		}
		
		public void Add(IProtocolAction action)
		{
			Mutex m = new Mutex();
			m.WaitOne();
			//transferq.Enqueue(action);
			tq.Add(action);
			m.ReleaseMutex();
		}
		
		public void StartTransfers()
		{
			if(threadxfer.ThreadState == ThreadState.Unstarted)
				threadxfer.Start();
			else if(threadxfer.ThreadState == ThreadState.Stopped)
			{
				threadxfer = new Thread(DoAction);
				threadxfer.Start();
			}
		}
		
		public void AbortAllTransfers()
		{
			this.threadxfer.Abort();
		}
		
		public void Reorder(XferFile file, int direction)
		{
			try
			{
				System.Collections.IEnumerator en = tq.GetEnumerator();
				int position = 0;
				int counter = 0;
				IProtocolAction action = null;
				while(en.MoveNext())
				{
					if(((IProtocolAction)en.Current).File.FileId == file.FileId)
					{
						action = en.Current as IProtocolAction;
						position = counter;
						
					}
					counter++;
				}
				
				tq.RemoveAt(position);
				
				if(direction == 0)
					tq.Insert(position-1, action);
				
				else if(direction == 1)
					tq.Insert(position+1, action);
			}
			catch{}
		}
		
		private void DoAction()
		{
			//while(transferq.Count > 0)
			while(tq.Count > 0)
			{
				//IProtocolAction a = (IProtocolAction)transferq.Dequeue();
				IProtocolAction a = tq[0];
				tq.RemoveAt(0);
				a.Execute(conn);				
			}
			OnQueueEmpty();
		}
	}
}
