using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;

namespace ThreadSafe
{
	#region LogStorage Class

	public class LogItem
	{
		public Color Color = Color.Black;
		public DateTime CreateTime = DateTime.Now;
		public FontStyle Style = FontStyle.Regular;
		public string LogMessage;

		public string DateStr
		{
			get { return CreateTime.ToString(" dd-MM-yyyy HH:mm:ss "); }
		}

		public override string ToString()
		{
			return DateTime.Now.ToString(" dd-MM-yyyy HH:mm:ss ") + LogMessage;
		}
		public  string ShortToString()
		{
			return DateTime.Now.ToString("HH:mm:ss ") + LogMessage;
		}
	}

	public class LogStorage
	{
		private readonly Queue<LogItem> fLogQueue = new Queue<LogItem>();
		private readonly Mutex LogMutex = new Mutex();
		public Color color = Color.Black;
		public Color ErrorColor = Color.Red;

		public LogStorage()
		{ }
		public LogStorage(Color c)
		{
			color = c;
		}
		public LogStorage(Color c,Color ErrColor)
		{
			color = c;
			ErrorColor = ErrColor;
		}

		public LogItem LogItems
		{
			get
			{
				LogItem res = null;
				LogMutex.WaitOne();
				if (fLogQueue.Count > 0)
					res = fLogQueue.Dequeue();
				LogMutex.ReleaseMutex();
				return res;
			}
			private set
			{
				if (value != null && !string.IsNullOrEmpty(value.LogMessage))
				{
					value.Color = color;
					LogMutex.WaitOne();
					fLogQueue.Enqueue(value);
					LogMutex.ReleaseMutex();
				}
			}
		}

		public int LogCount
		{
			get
			{
				LogMutex.WaitOne();
				int res = 0;
				if (fLogQueue != null)
					res = fLogQueue.Count;
				LogMutex.ReleaseMutex();
				return res;
			}
		}

		public string LogString
		{
			set
			{
				if (!string.IsNullOrEmpty(value))
				{
					LogItem li = new LogItem { LogMessage = value };
					LogItems = li;
				}
			}
			get
			{
				LogItem li = LogItems;
				if (li != null)
					return li.ToString();
				return null;
			}
		}
		
		public string ErrorString
		{
			set
			{
				if (!string.IsNullOrEmpty(value))
				{
					LogItem li = new LogItem { LogMessage = value };
					LogItems = li;
					li.Color = ErrorColor;
				}
			}
			get
			{
				LogItem li = LogItems;
				if (li != null)
					return li.ToString();
				return null;
			}
		}

		public LogItem[] GetAllItems
		{
			get
			{
				List<LogItem> res = new List<LogItem>();
				LogItem li = LogItems;
				while (li != null)
				{
					res.Add(li);
					li = LogItems;
				}
				return res.ToArray();
			}
		}

		public void Clear()
		{
			LogMutex.WaitOne();
			if (fLogQueue != null)
			{
				fLogQueue.Clear();
				fLogQueue.TrimExcess();
			}
			LogMutex.ReleaseMutex();			
		}
	}

	#endregion

	#region Thread safe List
	public class ThreadSafeList<T>
	{
		private readonly object syncObj = new object();
		private readonly List<T> innerlist = new List<T>();
		private readonly T NullValue = default(T);

		public T this[int index]
		{
			get
			{
				T res = NullValue;
				lock (syncObj)
				{
					if (index > -1 && index < innerlist.Count)
						res = innerlist[index];
				}
				return res;
			}
			set
			{
				lock (syncObj)
				{
					if (index > -1 && index < innerlist.Count)
						innerlist[index] = value;
				}
			}
		}
		public int Count
		{
			get
			{
				lock (syncObj)
				{
					return innerlist.Count;
				}
			}
		}
		public T[] ToArray
		{
			get
			{
				lock (syncObj)
				{
					return innerlist.ToArray();
				}
			}
		}

		public void Add(T item)
		{
			lock (syncObj)
			{
				innerlist.Add(item);
			}
		}
		public void Insert(int pos,T item)
		{
			lock (syncObj)
			{
				if (pos > -1 && pos <= innerlist.Count)
				{
					if (pos == innerlist.Count)
						innerlist.Add(item);
					else
						innerlist.Insert(pos, item);
				}
			}
		}
		public bool Remove(T item)
		{
			bool res;
			lock (syncObj)
			{
				res = innerlist.Remove(item);
				if(res)
					innerlist.TrimExcess();
			}
			return res;
		}
		public bool RemoveAt(int index)
		{
			bool res = false;
			lock (syncObj)
			{
				if (index > -1 && index < innerlist.Count)
				{
					res = true;
					innerlist.RemoveAt(index);
					innerlist.TrimExcess();
				}
			}
			return res;
		}
		public void AddRange(IEnumerable<T> collection)
		{
			if (collection == null)
				return;
			lock (syncObj)
			{
				innerlist.AddRange(collection);
			}
		}
		public bool Contains(T item)
		{
			bool res;
			lock(syncObj)
			{
				res = innerlist.Contains(item);
			}
			return res;
		}
		public void Clear()
		{
			lock (syncObj)
			{
				innerlist.Clear();
				innerlist.Capacity = 0;
			}
		}
	}
	#endregion

	#region Thread safe Queue
	public class ThreadSafeQueue<T> : Queue<T>
	{
		
		private readonly object syncObj = new object();
		private readonly Queue<T> innerqueue = new Queue<T>();
		private readonly T NullValue = default(T);

		public new int Count
		{
			get
			{
				lock (syncObj)
				{
					return innerqueue.Count;
				}
			}
		}
		public new  T[] ToArray
		{
			get
			{
				lock (syncObj)
				{
					return innerqueue.ToArray();
				}
			}
		}

		public new bool Contains(T itm)
		{
			lock (syncObj)
			{
				return innerqueue.Contains(itm);
			}
		}
		public new void Enqueue(T item)
		{
			lock (syncObj)
			{
				innerqueue.Enqueue(item);
			}
		}
		public new T Dequeue()
		{
			T res = NullValue;
			lock (syncObj)
			{
				if (innerqueue.Count > 0)
				{
					res = innerqueue.Dequeue();
					if (innerqueue.Count==0)
						innerqueue.TrimExcess();
				}
			}
			return res;
		}
		public new T Peek()
		{
			T res = NullValue;
			lock (syncObj)
			{
				if (innerqueue.Count > 0)
					res = innerqueue.Peek();
			}
			return res;
		}
		public void AddRange(IEnumerable<T> collection)
		{
			if (collection == null)
				return;
			lock (syncObj)
			{
				foreach (T itm in collection)
					innerqueue.Enqueue(itm);
			}
		}
		public new void Clear()
		{
			lock (syncObj)
			{
				innerqueue.Clear();
				innerqueue.TrimExcess();
			}
		}
	}

	#endregion
}