using System;
using System.IO;
using System.Collections;
using Server;
using Server.Accounting;

namespace Auberon.Chat
{
	public enum OnlineStatus { Online, Away, Hidden }
	
	public class Data
	{
		#region Statics
		public static void Save()
		{
			try { SavePlayerOptions(); }
			catch (Exception e)
			{
				//                 Errors.Report(General.Local(228), e);
				Console.WriteLine(e.Message);
				Console.WriteLine(e.Source);
				Console.WriteLine(e.StackTrace);
			}
			try { SaveFriends(); }
			catch (Exception e)
			{
				//                 Errors.Report(General.Local(230), e);
				Console.WriteLine(e.Message);
				Console.WriteLine(e.Source);
				Console.WriteLine(e.StackTrace);
			}
			try { SaveIgnores(); }
			catch (Exception e)
			{
				//                 Errors.Report(General.Local(232), e);
				Console.WriteLine(e.Message);
				Console.WriteLine(e.Source);
				Console.WriteLine(e.StackTrace);
			}
		}

		public static void Load()
		{
			try { LoadPlayerOptions(); }
			catch (Exception e)
			{
				//                 Errors.Report(General.Local(227), e);
				Console.WriteLine(e.Message);
				Console.WriteLine(e.Source);
				Console.WriteLine(e.StackTrace);
			}
			try { LoadFriends(); }
			catch (Exception e)
			{
				//                 Errors.Report(General.Local(229), e);
				Console.WriteLine(e.Message);
				Console.WriteLine(e.Source);
				Console.WriteLine(e.StackTrace);
			}
			try { LoadIgnores(); }
			catch (Exception e)
			{
				//                 Errors.Report(General.Local(231), e);
				Console.WriteLine(e.Message);
				Console.WriteLine(e.Source);
				Console.WriteLine(e.StackTrace);
			}
		}

		public static void SavePlayerOptions()
		{
			CleanUpData();
			
			if (!Directory.Exists(General.SavePath))
				Directory.CreateDirectory(General.SavePath);

			GenericWriter writer = new BinaryFileWriter(Path.Combine(General.SavePath, "PlayerOptions.bin"), true);

			writer.Write(0); // version

			writer.Write(s_Datas.Count);
			foreach (Data data in s_Datas.Values)
			{
				writer.Write(data.Mobile);
				data.SaveOptions(writer);
			}

			writer.Close();
		}

		public static void SaveFriends()
		{
			if (!Directory.Exists(General.SavePath))
				Directory.CreateDirectory(General.SavePath);

			GenericWriter writer = new BinaryFileWriter(Path.Combine(General.SavePath, "Friends.bin"), true);

			writer.Write(0); // version

			writer.Write(s_Datas.Count);
			foreach (Data data in s_Datas.Values)
			{
				writer.Write(data.Mobile);
				data.SaveFriends(writer);
			}

			writer.Close();
		}

		public static void SaveIgnores()
		{
			if (!Directory.Exists(General.SavePath))
				Directory.CreateDirectory(General.SavePath);

			GenericWriter writer = new BinaryFileWriter(Path.Combine(General.SavePath, "Ignores.bin"), true);

			writer.Write(0); // version

			writer.Write(s_Datas.Count);
			foreach (Data data in s_Datas.Values)
			{
				writer.Write(data.Mobile);
				data.SaveIgnores(writer);
			}

			writer.Close();
		}

		public static void LoadPlayerOptions()
		{
			if (!File.Exists(Path.Combine(General.SavePath, "PlayerOptions.bin")))
				return;

			using (FileStream bin = new FileStream(Path.Combine(General.SavePath, "PlayerOptions.bin"), FileMode.Open, FileAccess.Read, FileShare.Read))
			{
				GenericReader reader = new BinaryFileReader(new BinaryReader(bin));

				int version = reader.ReadInt();

				Mobile m = null;
				int count = reader.ReadInt();
				for (int i = 0; i < count; ++i)
				{
					m = reader.ReadMobile();
					if (m != null)
						GetData(m).LoadOptions(reader);
					else
						(new Data()).LoadOptions(reader);
				}
			}
		}

		public static void LoadFriends()
		{
			if (!File.Exists(Path.Combine(General.SavePath, "Friends.bin")))
				return;

			using (FileStream bin = new FileStream(Path.Combine(General.SavePath, "Friends.bin"), FileMode.Open, FileAccess.Read, FileShare.Read))
			{
				GenericReader reader = new BinaryFileReader(new BinaryReader(bin));

				int version = reader.ReadInt();

				Mobile m = null;
				int count = reader.ReadInt();
				for (int i = 0; i < count; ++i)
				{
					m = reader.ReadMobile();
					if (m != null)
						GetData(m).LoadFriends(reader);
					else
						(new Data()).LoadFriends(reader);
				}
			}
		}

		public static void LoadIgnores()
		{
			if (!File.Exists(Path.Combine(General.SavePath, "Ignores.bin")))
				return;

			using (FileStream bin = new FileStream(Path.Combine(General.SavePath, "Ignores.bin"), FileMode.Open, FileAccess.Read, FileShare.Read))
			{
				GenericReader reader = new BinaryFileReader(new BinaryReader(bin));

				int version = reader.ReadInt();

				Mobile m = null;
				int count = reader.ReadInt();
				for (int i = 0; i < count; ++i)
				{
					m = reader.ReadMobile();
					if (m != null)
						GetData(m).LoadIgnores(reader);
					else
						(new Data()).LoadIgnores(reader);
				}
			}
		}

		private static void CleanUpData()
		{
			Data data = null;
			foreach (Mobile m in new ArrayList(s_Datas.Keys))
			{
				data = (Data)s_Datas[m];

				if (m.Deleted || data.Mobile == null || data.Mobile.Deleted)
					s_Datas.Remove(data.Mobile);
				else if (data.Mobile.Player && data.Mobile.Account != null && ((Account)data.Mobile.Account).LastLogin < DateTime.Now - TimeSpan.FromDays(30))
					s_Datas.Remove(data.Mobile);
			}
		}
		#endregion

		#region Static Definitions
		public static int[] StatusHue = new int[]
		{
			67, // Online
			2, // Away
			32 // Hidden
		};
		
		public static string[] StatusText = new string[]
		{
			"Online", // Online
			"AFK", // Away
			"Hidden" // Hidden
		};
		
		private static Hashtable s_Datas = new Hashtable();
		public static Hashtable Datas { get { return s_Datas; } }
		#endregion
		
		public static Data GetData(Mobile m)
		{
			if (s_Datas[m] == null)
				return new Data(m);

			return (Data)s_Datas[m];
		}

		#region Class Definitions
		private Mobile c_Mobile;
		private OnlineStatus c_Status;
		private ArrayList c_Friends, c_Ignores;
		private int c_MsgHue;
		private int c_MsgHueStaff;
		private bool c_DontListenChat;
		
		public Mobile Mobile { get { return c_Mobile; } }
		public OnlineStatus Status { get { return c_Status; } set { c_Status = value; } }
		public int MsgHue { get { return c_MsgHue; } set { c_MsgHue = value; } }
		public int MsgHueStaff { get { return c_MsgHueStaff; } set { c_MsgHueStaff = value; } }
		public bool DontListenChat { get { return c_DontListenChat; } set { c_DontListenChat = value; } }
		public ArrayList Friends { get { return c_Friends; } }
		public ArrayList Ignores { get { return c_Ignores; } }
		#endregion

		#region Constructors
		public Data(Mobile m)
		{
			c_Mobile = m;
			c_Friends = new ArrayList();
			c_Ignores = new ArrayList();
			s_Datas[m] = this;
		}

		public Data()
		{
			c_Friends = new ArrayList();
			c_Ignores = new ArrayList();
		}

		#endregion

		#region Methods
		public void AddFriend(Mobile m)
		{
			if (c_Friends.Contains(m) || m == c_Mobile)
				return;

			c_Friends.Add(m);
			c_Mobile.SendMessage(33, m.Name + " je nyni na seznamu tvych pratel");
		}

		public void RemoveFriend(Mobile m)
		{
			if (!c_Friends.Contains(m))
				return;

			c_Friends.Remove(m);
			c_Mobile.SendMessage(33, m.Name + " byl odebran ze seznamu tvych pratel");
		}

		public void AddIgnore(Mobile m)
		{
			if (c_Mobile == m)
				return;

			if (c_Ignores.Contains(m) || m == c_Mobile)
				return;

			c_Ignores.Add(m);
			c_Mobile.SendMessage(33, m.Name + " je nyni na seznamu tebou ignorovanych hracu");
		}

		public void RemoveIgnore(Mobile m)
		{
			if (!c_Ignores.Contains(m))
				return;

			c_Ignores.Remove(m);
			c_Mobile.SendMessage(33, m.Name + " byl odebran ze seznamu tebou ignorovanych hracu");
		}

		public void SaveOptions(GenericWriter writer)
		{
			writer.Write(2); // Version
			
			writer.Write((int)c_MsgHueStaff);
			
			writer.Write((int)c_Status);
			writer.Write((int)c_MsgHue);
			writer.Write((bool)c_DontListenChat);
		}

		public void SaveFriends(GenericWriter writer)
		{
			writer.Write(1); // Version

			writer.WriteMobileList(c_Friends, true);
		}

		public void SaveIgnores(GenericWriter writer)
		{
			writer.Write(1); // Version

			writer.WriteMobileList(c_Ignores, true);
		}

		public void LoadOptions(GenericReader reader)
		{
			int version = reader.ReadInt();
			
			switch( version )
			{
				case 2:
				{
					c_MsgHueStaff = (int)reader.ReadInt();
					goto case 1;
				}
            case 1:
				{
			      c_Status = (OnlineStatus)reader.ReadInt();
			      c_MsgHue = (int)reader.ReadInt();
			      c_DontListenChat = (bool)reader.ReadBool();
					break;
				}
			}
		}

		public void LoadFriends(GenericReader reader)
		{
			int version = reader.ReadInt();

			c_Friends = reader.ReadMobileList();
		}

		public void LoadIgnores(GenericReader reader)
		{
			int version = reader.ReadInt();

			c_Ignores = reader.ReadMobileList();
		}
		#endregion
	}
}
