using System;
using Server;
using Server.Misc;
using System.Collections.Generic;
using System.Collections;
using Server.Commands;
using Server.Mobiles;
using Server.Network;
using Server.Gumps;

namespace Auberon.Chat
{
	public class SIMGumpList : Gump
	{
		public static void Initialize()
		{
			CommandSystem.Register("PM", AccessLevel.Player, new CommandEventHandler(SIM_OnCommand));
			CommandSystem.Register("IM", AccessLevel.Player, new CommandEventHandler(SIM_OnCommand));
		}

		[Usage("PM [filter]")]
		[Aliases("IM")]
		[Description("Lists all connected clients. Optionally filters results by name.")]
		private static void SIM_OnCommand(CommandEventArgs e)
		{
			if( e.Mobile.HasGump( typeof(SIMGumpMini) ) )
				e.Mobile.CloseGump( typeof(SIMGumpMini) );
			
			if( e.Mobile.HasGump( typeof(SIMGumpOptions) ) )
				e.Mobile.CloseGump( typeof(SIMGumpOptions) );

			if( e.Mobile.HasGump( typeof(SIMGumpList) ) )
				e.Mobile.CloseGump( typeof(SIMGumpList) );
			
			string filter = e.ArgString;
			
         if (filter != null && (filter = filter.Trim()).Length == 0)
				filter = null;
			else
				filter = filter.ToLower();
			
         if ( filter != null )
         {
			   List<NetState> states = NetState.Instances;
			   List<Mobile> list = new List<Mobile>();
			   
			   for (int i = 0; i < states.Count; ++i)
			   {
				  Mobile m = states[i].Mobile;
				
				  if ( m != null )
				  {
                  if ( m.RawName.ToLower() == filter && m != e.Mobile )
                     if ((Data.GetData(m).Status != OnlineStatus.Hidden && !Data.GetData(m).Ignores.Contains(e.Mobile)) || e.Mobile.AccessLevel > AccessLevel.Player)
                        list.Add( m );
              }
			   }
			   
            if ( list.Count == 0 )
               e.Mobile.SendMessage("Hrac {0} neni online nebo neexistuje.", e.ArgString);
            else if ( list.Count > 1 )
               e.Mobile.SendMessage("Momentalne je online {0} hracu se jmenem {1}. Prikaz neproveden.", list.Count, e.ArgString);
            else
               e.Mobile.SendGump( new SIMGumpChat( e.Mobile, list[0].NetState ) );
         }
         else				
            e.Mobile.SendGump(new SIMGumpList(e.Mobile));
		}

		public static bool OldStyle = PropsConfig.OldStyle;

		public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX;
		public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY;

		public static readonly int TextHue = PropsConfig.TextHue;
		public static readonly int TextOffsetX = PropsConfig.TextOffsetX;

		public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID;
		public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID;
		public static readonly int EntryGumpID = PropsConfig.EntryGumpID;
		public static readonly int BackGumpID = PropsConfig.BackGumpID;
		public static readonly int SetGumpID = PropsConfig.SetGumpID;

		public static readonly int SetWidth = PropsConfig.SetWidth;
		public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY;
		public static readonly int SetButtonID1 = PropsConfig.SetButtonID1;
		public static readonly int SetButtonID2 = PropsConfig.SetButtonID2;

		public static readonly int PrevWidth = PropsConfig.PrevWidth;
		public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY;
		public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1;
		public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2;

		public static readonly int NextWidth = PropsConfig.NextWidth;
		public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY;
		public static readonly int NextButtonID1 = PropsConfig.NextButtonID1;
		public static readonly int NextButtonID2 = PropsConfig.NextButtonID2;

		public static readonly int OffsetSize = PropsConfig.OffsetSize;

		public static readonly int EntryHeight = PropsConfig.EntryHeight;
		public static readonly int BorderSize = PropsConfig.BorderSize;

		private static bool PrevLabel = false, NextLabel = false;

		private static readonly int PrevLabelOffsetX = PrevWidth + 1;
		private static readonly int PrevLabelOffsetY = 0;

		private static readonly int NextLabelOffsetX = -29;
		private static readonly int NextLabelOffsetY = 0;

		private static readonly int EntryWidth = 180;
		private static readonly int EntryCount = 15;

		private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize;
		private static readonly int TotalHeight = OffsetSize + ((EntryHeight + OffsetSize) * (EntryCount + 1));

		private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
		private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize;

		private Mobile m_Owner;
		private List<Mobile> m_Mobiles;
		private int m_Page;
		private int m_What;

		private class InternalComparer : IComparer<Mobile>
		{
			public static readonly IComparer<Mobile> Instance = new InternalComparer();

			public InternalComparer()
			{
			}

			public int Compare(Mobile x, Mobile y)
			{
				if (x == null || y == null)
					throw new ArgumentException();

				if (x.AccessLevel > y.AccessLevel)
					return -1;
				else if (x.AccessLevel < y.AccessLevel)
					return 1;
				else
					return Insensitive.Compare(x.RawName, y.RawName);
			}
		}

		public SIMGumpList(Mobile owner)
			: this(owner, BuildList(owner, 0), 0, 0)
		{
		}

		public SIMGumpList(Mobile owner, List<Mobile> list, int page, int what)
			: base(GumpOffsetX, GumpOffsetY)
		{
			owner.CloseGump(typeof(SIMGumpList));

			m_Owner = owner;
			m_Mobiles = list;

			Initialize(page, what);
		}

		public static List<Mobile> BuildList(Mobile owner, int what)
		{
			List<Mobile> list = new List<Mobile>();
			List<NetState> states = NetState.Instances;
			
			if ( owner.Guild == null && what == 2)
				what = 0;
			
			for (int i = 0; i < states.Count; ++i)
			{
				Mobile m = states[i].Mobile;
				
				if (what == 0) //players
				{
					if (m != null && m.AccessLevel == AccessLevel.Player && (m == owner || (Data.GetData(m).Status != OnlineStatus.Hidden && !Data.GetData(m).Ignores.Contains(owner)) || owner.AccessLevel > AccessLevel.Player))// && (m == owner || !m.Hidden || owner.AccessLevel >= m.AccessLevel || (m is PlayerMobile && ((PlayerMobile)m).VisibilityList.Contains(owner))))
					{
						list.Add(m);
					}
				}
				else if (what == 1) //staff
				{
					if (m != null && m.AccessLevel > AccessLevel.Player && (m == owner || (Data.GetData(m).Status != OnlineStatus.Hidden && !Data.GetData(m).Ignores.Contains(owner)) || owner.AccessLevel > AccessLevel.Player))
					{
						list.Add(m);
					}
				}
				else if (what == 2) //guild
				{
					if (m != null && m.Guild == owner.Guild)
					{
						list.Add(m);
					}
				}
				else if (what == 3) //friends
				{
					if (m != null && Data.GetData(owner).Friends.Contains(m) && (Data.GetData(m).Status != OnlineStatus.Hidden && !Data.GetData(m).Ignores.Contains(owner) || owner.AccessLevel > AccessLevel.Player))
					{
						list.Add(m);
					}
				}
			}

			list.Sort(InternalComparer.Instance);

			return list;
		}

		public void Initialize(int page, int what)
		{
			m_Page = page;
			m_What = what;

			int count = m_Mobiles.Count - (page * EntryCount);

			if (count < 0)
				count = 0;
			else if (count > EntryCount)
				count = EntryCount;

			string WhatText = "Players";
			
			if ( m_What == 1 ) WhatText = "Staff";
			else if ( m_What == 2 ) WhatText = "Guild";
			else if ( m_What == 3 ) WhatText = "Friends";
			int totalHeight = OffsetSize + ((EntryHeight + OffsetSize) * (count + 1));

			AddPage(0);

			AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID);
			AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, OffsetGumpID);

			int x = BorderSize + OffsetSize;
			int y = BorderSize + OffsetSize;

			int emptyWidth = TotalWidth - PrevWidth - NextWidth - (OffsetSize * 4) - (OldStyle ? SetWidth + OffsetSize : 0);

			if (!OldStyle)
				AddImageTiled(x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, EntryGumpID);

			AddLabel(x + TextOffsetX, y, TextHue, String.Format("{3}: {2}  (Page: {0}/{1})", page + 1, (m_Mobiles.Count + EntryCount - 1) / EntryCount, m_Mobiles.Count, WhatText));

			x += emptyWidth + OffsetSize;

			if (OldStyle)
				AddImageTiled(x, y, TotalWidth - (OffsetSize * 3) - SetWidth, EntryHeight, HeaderGumpID);
			else
				AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID);

			if (page > 0)
			{
				AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1, GumpButtonType.Reply, 0);
				AddTooltip( 1011067 ); //Previous page

				if (PrevLabel)
					AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous");
			}

			x += PrevWidth + OffsetSize;

			if (!OldStyle)
				AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID);

			if ((page + 1) * EntryCount < m_Mobiles.Count)
			{
				AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 2, GumpButtonType.Reply, 1);
				AddTooltip( 1011066 ); //Next page
				
				if (NextLabel)
					AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next");
			}

			for (int i = 0, index = page * EntryCount; i < EntryCount && index < m_Mobiles.Count; ++i, ++index)
			{
				x = BorderSize + OffsetSize;
				y += EntryHeight + OffsetSize;

				Mobile m = m_Mobiles[index];
				
				string nm;
				if (m.Deleted)
					nm = "(deleted)";
				else
				{
					nm = m.RawName;
					if (Data.GetData(m).Status == OnlineStatus.Away)
						nm = nm + " (AFK)";
					else if (Data.GetData(m).Status == OnlineStatus.Hidden)
						nm = nm + " (H)";
					
					if (Data.GetData(m_Owner).Ignores.Contains(m))
						nm = String.Format("{0}{1}", nm, (Data.GetData(m).Status == OnlineStatus.Online) ? " (ig)" : "(ig)");
				}

				AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
				AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, GetHueFor(m), nm);

				x += EntryWidth + OffsetSize;

				if (SetGumpID != 0)
					AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID);

				if (m_Owner.AccessLevel == AccessLevel.Player || m.NetState == null || m.Deleted || m == m_Owner || m_Owner.AccessLevel < m.AccessLevel )
				{}
				else
				{
					AddButton(x + (SetOffsetX - 22), y + SetOffsetY, 9702, 9703, (i * 2) + 3 + 1, GumpButtonType.Reply, 0);
					AddTooltip( 3005097 ); //Goto
				}
            
            if (m.NetState == null || m.Deleted || m == m_Owner ||
				    ((Data.GetData(m).Ignores.Contains(m_Owner) || Data.GetData(m_Owner).Status == OnlineStatus.Hidden || Data.GetData(m).Status == OnlineStatus.Hidden) &&
				     m_Owner.AccessLevel == AccessLevel.Player))
				{}
				else
				{
					AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, (i * 2) + 3 + 0, GumpButtonType.Reply, 0);
					AddTooltip( 3000157 ); //Post Message
				}
			}
			
			//dolni cudly
			int hght = (BorderSize * 2) + (EntryHeight * 3) + OffsetSize*2;

			y += 35;
			AddBackground(0, y, BackWidth, hght, BackGumpID);
			AddImageTiled(BorderSize + 32, y + BorderSize, 75 + TextOffsetX, hght + (OffsetSize * 2) - (BorderSize * 2), OffsetGumpID);
			//all
			y += (BorderSize + OffsetSize);
			
			int simage = 30041;
			int st = 0;
			if (Data.GetData(m_Owner).Status == OnlineStatus.Away)
			{
				simage = 30027;
				st = 1;
			}
			else if (Data.GetData(m_Owner).Status == OnlineStatus.Hidden)
			{
				simage = 30020;
				st = 2;
			}

			//status
			AddButton(BackWidth - BorderSize - 30, y, simage, simage, 9993, GumpButtonType.Reply, 0);
			AddTooltip( 1072845 ); //Status
			AddLabelCropped(BorderSize + OffsetSize + 32 + 85, y + 5, 45, EntryHeight, Data.StatusHue[st], Data.StatusText[st].ToUpper());
			
			//Players
			AddButton(BorderSize, y, (m_What == 0) ? 4009 : 4008, 4010, 9990, GumpButtonType.Reply, 0);
			AddTooltip( 3005145 ); //Players Only
			AddImageTiled(BorderSize + OffsetSize + 32, y, 75, EntryHeight, EntryGumpID);
			AddLabelCropped(BorderSize + OffsetSize + 32 + TextOffsetX, y, 75 - TextOffsetX, EntryHeight, TextHue, "Players");
			//staff
			y += (EntryHeight + OffsetSize);
			AddButton(BorderSize, y, (m_What == 1) ? 4003 : 4002, 4004, 9991, GumpButtonType.Reply, 0);
			AddTooltip( 1074772 ); //GM
			AddImageTiled(BorderSize + OffsetSize + 32, y, 75, EntryHeight, EntryGumpID);
			AddLabelCropped(BorderSize + OffsetSize + 32 + TextOffsetX, y, 75 - TextOffsetX, EntryHeight, TextHue, "Staff");
			//friends
			y += (EntryHeight + OffsetSize);
			AddButton(BorderSize, y, (m_What == 3) ? 4012 : 4011, 4013, 9994, GumpButtonType.Reply, 0);
			AddTooltip( 1011243 ); //View Friends List
			AddImageTiled(BorderSize + OffsetSize + 32, y, 75, EntryHeight, EntryGumpID);
			AddLabelCropped(BorderSize + OffsetSize + 32 + TextOffsetX, y, 75 - TextOffsetX, EntryHeight, TextHue, "Friends");
			
			if ( m_Owner.Guild != null )
			{
				AddImageTiled(BorderSize + 32 + 110, y - OffsetSize, 45 + (TextOffsetX * 2), EntryHeight + (OffsetSize * 2), OffsetGumpID);
				AddButton(BorderSize + 110, y, (m_What == 2) ? 4027 : 4026, 4028, 9992, GumpButtonType.Reply, 0);
				AddTooltip( 1063455 ); //Guild Members
				AddImageTiled(BorderSize + OffsetSize + 32 + 110, y, 45 + TextOffsetX, EntryHeight, EntryGumpID);
				AddLabelCropped(BorderSize + OffsetSize + 32 + TextOffsetX + 110, y, 45 - TextOffsetX, EntryHeight, TextHue, "Guild");
			}
			else
			{
				AddLabelCropped(BorderSize + OffsetSize + 32 + TextOffsetX + 90, y, 45 - TextOffsetX, EntryHeight, 143, ServerList.ServerName.ToString());
			}
			
			AddButton(BackWidth - BorderSize - 10, y - 2, 2435, 2436, 9995, GumpButtonType.Reply, 0);
			AddTooltip( 1015326 ); //Options
			AddButton(BackWidth - BorderSize - 10, y + 10, 2437, 2438, 9996, GumpButtonType.Reply, 0);
			AddTooltip( 3002085 ); //Minimize
		}

		private static int GetHueFor(Mobile m)
		{
			switch (m.AccessLevel)
			{
					case AccessLevel.Owner: return 14;
					case AccessLevel.Developer: return 14;
					case AccessLevel.Administrator: return 14;
					case AccessLevel.Seer: return 14;
					case AccessLevel.GameMaster: return 14;
					case AccessLevel.Counselor: return 30;
				case AccessLevel.Player:
				default:
					{
						// 						if (m.Kills >= 5)
						// 							return 33;
						// 						else if (m.Criminal)
						// 							return 945;

						return 1088;
					}
			}
		}

		public override void OnResponse(NetState state, RelayInfo info)
		{
			Mobile from = state.Mobile;

			switch (info.ButtonID)
			{
				case 0: // Closed
					{
						return;
					}
				case 1: // Previous
					{
						if (m_Page > 0)
							from.SendGump(new SIMGumpList(from, m_Mobiles, m_Page - 1, m_What));

						break;
					}
				case 2: // Next
					{
						if ((m_Page + 1) * EntryCount < m_Mobiles.Count)
							from.SendGump(new SIMGumpList(from, m_Mobiles, m_Page + 1, m_What));

						break;
					}
				case 9990: // all
					{
						from.SendGump(new SIMGumpList(from, BuildList(from, 0), 0, 0));
						break;
					}
				case 9991: // staff
					{
						from.SendGump(new SIMGumpList(from, BuildList(from, 1), 0, 1));
						break;
					}
				case 9992: // guild
					{
						from.SendGump(new SIMGumpList(from, BuildList(from, 2), 0, 2));
						break;
					}
				case 9993: // status
					{
						if (Data.GetData(from).Status == OnlineStatus.Online)
							Data.GetData(from).Status = OnlineStatus.Away;
						else if (Data.GetData(from).Status == OnlineStatus.Away)
							Data.GetData(from).Status = OnlineStatus.Hidden;
						else if (Data.GetData(from).Status == OnlineStatus.Hidden)
							Data.GetData(from).Status = OnlineStatus.Online;
						
						from.SendGump(new SIMGumpList(from, m_Mobiles, m_Page, m_What));
						break;
					}
				case 9994: // friend
					{
						from.SendGump(new SIMGumpList(from, BuildList(from, 3), 0, 3));
						break;
					}
				case 9995: // options
					{
						if( from.HasGump( typeof(SIMGumpOptions) ) )
							from.CloseGump( typeof(SIMGumpOptions) );

						from.SendGump(new SIMGumpOptions(from));
						break;
					}
				case 9996: // minimize
					{
						if( from.HasGump( typeof(SIMGumpMini) ) )
							from.CloseGump( typeof(SIMGumpMini) );

						from.SendGump(new SIMGumpMini());
						break;
					}
				default:
					{
                  int buttonID = info.ButtonID;
                  buttonID -= 3;

                  int type = buttonID % 2;                  
                  int index = (m_Page * EntryCount) + (buttonID / 2);

						if (index >= 0 && index < m_Mobiles.Count)
						{
							Mobile m = m_Mobiles[index];

							if (m.Deleted)
							{
								from.SendMessage("Tento hrac jiz neexistuje.");
								from.SendGump(new SIMGumpList(from, m_Mobiles, m_Page, m_What));
							}
							else if (m.NetState == null || (Data.GetData(m).Ignores.Contains(from) && from.AccessLevel == AccessLevel.Player))
							{
								from.SendMessage("Hrac jiz neni online.");
								from.SendGump(new SIMGumpList(from, m_Mobiles, m_Page, m_What));
							}
							else if (type == 0 && (m == from || Data.GetData(m).Status != OnlineStatus.Hidden || from.AccessLevel > AccessLevel.Player))
							{
								from.SendGump(new SIMGumpChat(from, m.NetState));
								from.SendGump(new SIMGumpList(from, m_Mobiles, m_Page, m_What));
							}
							else if (type == 1 && from.AccessLevel > AccessLevel.Player) //go
							{
                        if ( m.Map == null || m.Map == Map.Internal )
                        {
                        	from.SendMessage( "Tento hrac neni ve svete (mapa internal nebo null)." );
                        }
                        else
                        {
                        	from.MoveToWorld( m.Location, m.Map );
                        	CommandLogging.WriteLine( from, "{0} {1} going to {2}, Location {3}, Map {4}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( m ), m.Location, m.Map );
                        }
                        from.SendGump(new SIMGumpList(from, m_Mobiles, m_Page, m_What));
                     }
							else
							{
								from.SendMessage("Hrac nenalezen.");
								from.SendGump(new SIMGumpList(from, m_Mobiles, m_Page, m_What));
							}
						}

						break;
					}
			}
		}
	}
}
