/**********************************************************
RunUO AoV C# script file
Official Age of Valor Script :: www.uovalor.com
Last modified by Red Squirrel on Sep-16-2011 09:08:50pm
Filepath: scripts\Misc\Cleanup.cs
Lines of code: 188

Description: 

***********************************************************/


using System;
using System.Collections;
using Server;
using Server.Items;
using Server.Multis;
using Server.Mobiles;
using System.Collections.Generic;
using System.IO;
using Server.Accounting;

namespace Server.Misc
{
	public class Cleanup
	{
		public static void Initialize()
		{
			Timer.DelayCall( TimeSpan.FromSeconds( 2.5 ), new TimerCallback( Run ) );
			
			new CleanupTimer().Start();
		}

		public static void Run()
		{
			List<Item> items = new List<Item>();
			List<Item> validItems = new List<Item>();
			List<Mobile> hairCleanup = new List<Mobile>();

			int boxes = 0;

			foreach ( Item item in World.Items.Values )
			{
				if ( item.Map == null )
				{
					items.Add( item );
					continue;
				}
				else if ( item is CommodityDeed )
				{
					CommodityDeed deed = (CommodityDeed)item;

					if ( deed.Commodity != null )
						validItems.Add( deed.Commodity );

					continue;
				}
				else if ( item is BaseHouse )
				{
					BaseHouse house = (BaseHouse)item;

					foreach ( RelocatedEntity relEntity in house.RelocatedEntities )
					{
						if ( relEntity.Entity is Item )
							validItems.Add( (Item)relEntity.Entity );
					}

					foreach ( VendorInventory inventory in house.VendorInventories )
					{
						foreach ( Item subItem in inventory.Items )
							validItems.Add( subItem );
					}
				}
				else if ( item is BankBox )
				{
					BankBox box = (BankBox)item;
					Mobile owner = box.Owner;

					if ( owner == null )
					{
						items.Add( box );
						++boxes;
					}
					else if ( box.Items.Count == 0 )
					{
						items.Add( box );
						++boxes;
					}

					continue;
				}
				else if ( (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair) )
				{
					object rootParent = item.RootParent;

					if ( rootParent is Mobile )
					{
						Mobile rootMobile = (Mobile)rootParent;
						if ( item.Parent != rootMobile && rootMobile.AccessLevel == AccessLevel.Player )
						{
							items.Add( item );
							continue;
						}
						else if( item.Parent == rootMobile )
						{
							hairCleanup.Add( rootMobile );
							continue;
						}
					}
				}

				if ( item.Parent != null || item.Map != Map.Internal || item.HeldBy != null )
					continue;

				if ( item.Location != Point3D.Zero )
					continue;

				if ( !IsBuggable( item ) )
					continue;

				items.Add( item );
			}

			for ( int i = 0; i < validItems.Count; ++i )
			{
			items.Remove( validItems[i] );
			}

			if ( items.Count > 0 )
			{
				if ( boxes > 0 )
					Console.Write( "Cleanup: Detected {0} inaccessible items, including {1} bank boxes, removing..", items.Count, boxes );
				else
					Console.Write( "Cleanup: Detected {0} inaccessible items, removing..", items.Count );

				using ( StreamWriter op = new StreamWriter( "output\\cleanup.log",true ) )  //(true for append)
				{
					System.Debugger.Write("true",false, "{0} Items deleted on {1} ",items.Count,DateTime.Now);
					
					for ( int i = 0; i < items.Count; ++i )
					{
						Type type = items[i].GetType();
						
						System.Debugger.Write("cleanup",false,"{0} typeof({1}) {2}              {3} {4} {5}  {6}",items[i].Serial,type.Name,items[i].Name,items[i].X,items[i].Y,items[i].Z,items[i].Map);
						items[i].Delete();
					}
				}
				
				Console.WriteLine("done.");
			}

			if ( hairCleanup.Count > 0 )
			{
				Console.Write( "Cleanup: Detected {0} hair and facial hair items being worn, converting to their virtual counterparts...", hairCleanup.Count );

				for ( int i = 0; i < hairCleanup.Count; i++ )
					hairCleanup[i].ConvertHair();
					
				Console.WriteLine("done.");
			}
			
			
			
			

			//delete empty accounts:
			/*
			List<Account> delacc = new List<Account>();
	
			foreach (KeyValuePair<string, IAccount> kvp in Accounts.m_Accounts)
			{
				if (kvp.Value is Account)
				{
					Account tdel = kvp.Value as Account;
				
					if(tdel.CharAmt<=0)
					{
					delacc.Add(tdel);			
					}				
				}
			}				

		
			if(delacc.Count>0)
			{
				Console.Write("Found {0} empty accounts. Deleting...",delacc.Count);
				for(int i=0;i<delacc.Count;i++)
				{
				delacc[i].Delete();
				}	
				Console.WriteLine("done.");
			}
			
			*/
		}

		
		
		

		public static bool IsBuggable(Item item)
		{
			if ( item is Fists )
				return false;

			if ( item is ICommodity || item is Multis.BaseBoat
				|| item is Fish || item is BigFish
				|| item is BasePotion || item is Food || item is CookableFood
				|| item is SpecialFishingNet || item is BaseMagicFish
				|| item is Shoes || item is Sandals
				|| item is Boots || item is ThighBoots
				|| item is TreasureMap || item is MessageInABottle
				|| item is BaseArmor || item is BaseWeapon
				|| item is BaseClothing
				|| (item is BaseJewel && Core.AOS)
				|| item is Bandage)
				return true;

			return false;
		}
		
		
		
		
		
		
		//runs occasionally to check for decayed items
		public static bool DecayItems()
		{
			System.Debugger.Write("cleanup","Running decay cleanup...");
			
			List<Item> todelete = new List<Item>();
			
			int limiter=100;
			bool notdone=false;
			
			
			foreach ( Item item in World.Items.Values )
			{
				if (item.Decays && item.Parent == null && item.Map != Map.Internal && DateTime.Now > (item.LastMoved + item.DecayTime))
				{					
					todelete.Add(item);
					limiter--;
					if(limiter==0)
					{
						notdone=true;
						break;					
					}
				}					
			}
			
			foreach ( Item item in todelete )
			{
				System.Debugger.Write("cleanup",false,"{0} Decayed",item);
				item.Delete();
			}
			System.Debugger.Write("cleanup",false,"Done running decay cleanup");


			return !notdone;
		}
		
		
		
		
		public class CleanupTimer : Timer
		{
			private DateTime NextCheck;
			
			public CleanupTimer() : base( TimeSpan.FromMinutes(1),TimeSpan.FromMinutes(1))
			{
			}

			protected override void OnTick()
			{
				if(NextCheck<DateTime.Now)
				{
					if(DecayItems())
					{
						NextCheck=DateTime.Now+TimeSpan.FromMinutes(10);
					}					
				}
			}
		}		
	}
}