/**********************************************************
RunUO 2.0 AoV C# script file
Official Age of Valor Script :: www.uovalor.com
Last modified by Red Squirrel on Jan-02-2010 02:32:22pm
Filepath: scripts\_custom\engines\Event System\events\pvptourney\PvpTourneyEventController.cs
Lines of code: 285
***********************************************************/


using Server;
using Server.Mobiles;
using System;
using System.Collections.Generic;


namespace Server.EventSystem
{
	public class PvpTourneyEventController : BaseEventController
	{

		 

		
		[Constructable]
		public PvpTourneyEventController() : base()
		{
		}
		

		
		public override bool RunAutoTeamBalance { get { return false; } }
		public override int m_MinTeams { get { return  0; } }
		public override int m_MaxTeams { get { return  0; } }
		public override TimeSpan TickInterval { get { return TimeSpan.FromSeconds(10); } }
				
		
		private List<TourneyArena> Arenas = new List<TourneyArena>();
		private List<Mobile> fighters = new List<Mobile>(); //players that are queued to fight
		private List<Mobile> fightersdone = new List<Mobile>(); //players that won a fight go here (loosers get deleted)
		
		private int NextMatchNum=0;
		
		
		
		[CommandProperty( AccessLevel.GameMaster )]
		public int ArrayCountArenas
		{
			get{return Arenas!=null ? Arenas.Count : -1;}
		}		
		
		[CommandProperty( AccessLevel.GameMaster )]
		public int ArrayCountFighters
		{
			get{return fighters!=null ? fighters.Count : -1;}
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int ArrayCountFightersdone
		{
			get{return fightersdone!=null ? fightersdone.Count : -1;}
		}
				
		
		
		//this function moves all fightersdone into fighters, if fighters is empty or less then 2
		public void SetNewSeries()
		{
			ArrayDefrag();
			Debugger.Write("pvptourney","{0} SetNewSeries() start",this);
			if(fighters.Count<2 && AreAllArenasFree())
			{
				Debugger.Write("pvptourney","New round starting");
			
				for(;fightersdone.Count>0;)
				{
					Debugger.Write("pvptourney","{0} SetNewSeries: {1}",this,fightersdone[0]);
					fighters.Add(fightersdone[0]);
					fightersdone.RemoveAt(0);
				}
			}
			Debugger.Write("pvptourney","{0} SetNewSeries() end",this);		
			Modify();			
		}
		
		
		
		//this function removes deleted/null objects from event arrays.  This is cpu intense so should only be called when really needed.
		private void ArrayDefrag()
		{		
			Debugger.Write("pvptourney","{0} ArrayDefrag()",this);
			//Arenas
			//==========================================================================
			List <TourneyArena> itemstodel = new List<TourneyArena>();
			
			foreach(TourneyArena mob in Arenas)
			{
				if(mob==null || mob.Deleted)itemstodel.Add(mob);			
			}
			
			foreach(TourneyArena mob in itemstodel)
			{
				Arenas.Remove(mob);
			}
			itemstodel.Clear();
		
			
			//fighters
			//==========================================================================
			List <Mobile> mobstodel = new List<Mobile>();
			
			foreach(Mobile mob in fighters)
			{
				if(mob==null || mob.Deleted)mobstodel.Add(mob);			
			}
			
			foreach(Mobile mob in mobstodel)
			{
				fighters.Remove(mob);
			}
			mobstodel.Clear();
			
			
			//fightersdone
			//==========================================================================

			
			foreach(Mobile mob in fightersdone)
			{
				if(mob==null || mob.Deleted)mobstodel.Add(mob);			
			}
			
			foreach(Mobile mob in mobstodel)
			{
				fightersdone.Remove(mob);
			}
			mobstodel.Clear();
			
			Modify();
		}		
		
	
		
		
		public int GetNextMatchNum()
		{
			NextMatchNum++;
			return NextMatchNum;
		}
		
		
		public void AddArena(TourneyArena arena)
		{
			Debugger.Write("pvptourney","{0} Adding arena {1}",this,arena);
			Arenas.Add(arena);
			Modify();
		}
		
		public void RemoveArena(TourneyArena arena)
		{
			Debugger.Write("pvptourney","{0} Removing arena {1}",this,arena);
			Arenas.Remove(arena);
			Modify();
		}
		
		
		public TourneyArena GetSpareArena()
		{
			Debugger.Write("pvptourney","{0} Checking for spare arena out of {1} arenas...",this,Arenas.Count);
			
			
			foreach(TourneyArena ta in Arenas)
			{
				if(ta!=null && ta.IsAvailable)
				{
					Debugger.Write("pvptourney","{0} arena available: {1}",this,ta);
					return ta;
				}
			}
			
			
			
			Debugger.Write("pvptourney","{0} No spare arena found",this);
			
			return null;
		}
		
		public bool AreAllArenasFree()
		{
			Debugger.Write("pvptourney","{0} calling AreAllArenasFree()",this);
			foreach(TourneyArena ta in Arenas)
			{
				if(ta!=null && !ta.IsAvailable)
				{
					Debugger.Write("pvptourney","{0} is not free, returning false",ta);
					return false;
				}
			}
			Debugger.Write("pvptourney","{0} all arenas found free in  AreAllArenasFree()",this);
			return true;
		}
		
		
		
		protected override void OnStartEvent()
		{
			//add all registered players to our own array (don't want to actually alter main array as its part of event sys)
			
			Debugger.Write("pvptourney","{0} Adding registered members to fighters list...",this);
			
			foreach(Mobile reg in GetRegisteredMobs())
			{
				Debugger.Write("pvptourney","{0} added {1}",this,reg);
				fighters.Add(reg);
			}
			
			Modify();
		}
		
		
		protected override void OnStopEvent()
		{			
			
			fighters.Clear();
			fightersdone.Clear();
			
			NextMatchNum=0;
		}
		
		
	
	
		//returns array of fighters not counting offline people
		public List<Mobile> GetAvailableFighters(int max)
		{
			List<Mobile> ava = new List<Mobile>();
			
			SetNewSeries();
			
			Debugger.Write("pvptourney","{0} Getting up to {1} available fighters...",this,max);
			
			foreach(Mobile reg in fighters)
			{
				Debugger.Write("pvptourney","{0} {1}...",this,reg);
				
				if(reg.NetState!=null || reg is BaseCreature)
				{
					Debugger.Write("pvptourney","{0} available: {1}",this,reg);
					ava.Add(reg);
					max--;
				}
				else Debugger.Write("pvptourney","{0} not available: {1}",this,reg);
				
				if(max<=0)break;
			}
		
			return ava;
		}
		
		
		public void EndMatchTeleport(Mobile mob,bool won,Point3D loc)
		{
			if(won)fightersdone.Add(mob);
						
			mob.Team=0;
			Spells.Chivalry.RemoveCurseSpell.RemoveCurses(mob);
			mob.HitsPerc=100;
			mob.StamPerc=100;
			mob.ManaPerc=100;			
			
			MoveMobile(mob,loc,TeleportStartMap);
		}


		public void DebugLists()
		{
			Debugger.Write("pvptourneyarrays","{0} Showing fighters...",this);			
			foreach(Mobile mob in fighters)
			{
				Debugger.Write("pvptourneyarrays",false,"{0} {1}",this,mob);
			}
		
			Debugger.Write("pvptourneyarrays","{0} Showing fightersdone...",this);			
			foreach(Mobile mob in fightersdone)
			{
				Debugger.Write("pvptourneyarrays",false,"{0} {1}",this,mob);
			}
		
			Debugger.Write("pvptourneyarrays","{0} Showing Arenas...",this);			
			foreach(Item mob in Arenas)
			{
				Debugger.Write("pvptourneyarrays",false,"{0} {1}",this,mob);
			}		
		
		}
		


		protected override void OnEventTick()
		{
			Debugger.Write("pvptourney","{0} OnEventTick() ",this);
			
			DebugLists();			
			
			//Check if we have a spare arena to start a match on:
			TourneyArena ta = GetSpareArena();
			if(ta!=null)
			{
				//we got an arena, now lets see if theres some people that want to dual

				List<Mobile> af = GetAvailableFighters(MembersPerTeam*2);
				
				if(af.Count>=2)
				{
					PvPMatch match = new PvPMatch(ta,this);
					
					Debugger.Write("pvptourney","enough people to start a match, prepping...");
					
					for(int i=0;(i+1)<(af.Count);i+=2)
					{
						Debugger.Write("pvptourney","forloop i={0} / af.Count={1}",i,af.Count);
						Debugger.Write("pvptourney","adding af[{0}] {1}...",i,af[i]);
						match.AddDualer(af[i],1);
						fighters.Remove(af[i]);
						
						Debugger.Write("pvptourney","adding af[{0}+1] {1}...",i,af[i+1]);
						match.AddDualer(af[i+1],2);				
						fighters.Remove(af[i+1]);						
					}
					
					ta.StartMatch(match);				
				}
				else
				{
					//Is event over?  Lets make sure:
					Debugger.Write("pvptourney","{0} tourney may be over",this);
					DebugLists();
					

					if(AreAllArenasFree())
					{	
						//event is over, finalize everything

						DebugLists();											
											
						StopEvent();			
					}
				}
				
				af.Clear();
			}
		}
		
		
		
		
		
		
		public PvpTourneyEventController( Serial serial ) : base( serial )
		{
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			writer.Write( (int) 0 ); // version		

			ArrayDefrag();

			writer.Write(Arenas.Count);
			foreach(TourneyArena obj in Arenas)
			{
				writer.Write(obj);
			}
			
			writer.Write(fighters.Count);
			foreach(Mobile obj in fighters)
			{
				writer.Write(obj);
			}
			
			writer.Write(fightersdone.Count);
			foreach(Mobile obj in fightersdone)
			{
				writer.Write(obj);
			}	

			writer.Write(NextMatchNum);
			
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			int version = reader.ReadInt();	
			
			Arenas = new List<TourneyArena>();
			fighters = new List<Mobile>(); 
			fightersdone = new List<Mobile>();
		
			int tmpcount=reader.ReadInt();
			for(int i=0;i<tmpcount;i++)
			{	
				Item toadd=reader.ReadItem();
				if(toadd is TourneyArena)Arenas.Add((TourneyArena)toadd);
			}
			
			tmpcount=reader.ReadInt();
			for(int i=0;i<tmpcount;i++)
			{	
				Mobile toadd=reader.ReadMobile();
				fighters.Add(toadd);
			}	

			tmpcount=reader.ReadInt();
			for(int i=0;i<tmpcount;i++)
			{	
				Mobile toadd=reader.ReadMobile();
				fightersdone.Add(toadd);
			}	

			NextMatchNum=reader.ReadInt();
		
		}		
		
		

	}

}