/**********************************************************
RunUO 2.0 AoV C# script file
Official Age of Valor Script :: www.uovalor.com
Last modified by 
Filepath: scripts\Commands\Dupe.cs
Lines of code: 171
***********************************************************/


using System;
using System.Reflection;
using Server.Items;
using Server.Targeting;

namespace Server.Commands
{
	public class Dupe
	{
		public static void Initialize()
		{
			CommandSystem.Register( "Dupe", AccessLevel.GameMaster, new CommandEventHandler( Dupe_OnCommand ),true );
			CommandSystem.Register( "DupeInBag", AccessLevel.GameMaster, new CommandEventHandler( DupeInBag_OnCommand ),true );
			CommandSystem.Register( "DupeInFel", AccessLevel.GameMaster, new CommandEventHandler( DupeInFel_OnCommand ),true );
		}

		[Usage( "Dupe [amount]" )]
		[Description( "Dupes a targeted item." )]
		private static void Dupe_OnCommand( CommandEventArgs e )
		{
			int amount = 1;
			if ( e.Length >= 1 )
				amount = e.GetInt32( 0 );
			e.Mobile.Target = new DupeTarget( false, amount > 0 ? amount : 1 );
			e.Mobile.SendMessage( "What do you wish to dupe?" );
		}

		[Usage( "DupeInBag <count>" )]
		[Description( "Dupes an item at it's current location (count) number of times." )]
		private static void DupeInBag_OnCommand( CommandEventArgs e )
		{
			int amount = 1;
			if ( e.Length >= 1 )
				amount = e.GetInt32( 0 );

			e.Mobile.Target = new DupeTarget( true, amount > 0 ? amount : 1 );
			e.Mobile.SendMessage( "What do you wish to dupe?" );
		}
		
		[Usage( "DupeInFel " )]
		[Description( "Dupes an to the opposite facet" )]
		private static void DupeInFel_OnCommand( CommandEventArgs e )
		{

			e.Mobile.Target = new DupeTarget( true, -1 );  //ammount -1 indicates we dupe to other facet
			e.Mobile.SendMessage( "What do you wish to dupe?" );
		}		

		private class DupeTarget : Target
		{
			private bool m_InBag;
			private int m_Amount;

			public DupeTarget( bool inbag, int amount )
				: base( 15, false, TargetFlags.None )
			{
				m_InBag = inbag;
				m_Amount = amount;
			}

			protected override void OnTarget( Mobile from, object targ )
			{
				bool done = false;
				if ( !( targ is Item ) )
				{
					from.SendMessage( "You can only dupe items." );
					return;
				}

				bool infel= m_Amount==-1;
				
				if(infel)m_Amount=1;
				
				CommandLogging.WriteLine( from, "{0} {1} duping {2} (inBag={3}; amount={4})", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( targ ), m_InBag, m_Amount );
				
				Item copy = (Item)targ;
				Container pack;

				if(infel)
				{
					if(copy.ParentEntity!=null ||copy.Parent!=null)
					{				
					from.SendMessage( "You can only dupe items that are on the ground." );
					return;
					}
					if(copy.Map!=Map.Felucca && copy.Map!=Map.Trammel)
					{
					from.SendMessage( "You can only dupe this way with items that are in fel or trammel" );
					return;
					}					
				}			
				
				

				if ( m_InBag )
				{
					if ( copy.Parent is Container )
						pack = (Container)copy.Parent;
					else if ( copy.Parent is Mobile )
						pack = ( (Mobile)copy.Parent ).Backpack;
					else
						pack = null;
				}
				else
					pack = from.Backpack;

				Type t = copy.GetType();

				//ConstructorInfo[] info = t.GetConstructors();

				ConstructorInfo c = t.GetConstructor( Type.EmptyTypes );

				if ( c != null )
				{
					try
					{
						from.SendMessage( "Duping {0}...", m_Amount );
						for ( int i = 0; i < m_Amount; i++ )
						{
							object o = c.Invoke( null );

							if ( o != null && o is Item )
							{
								Item newItem = (Item)o;
								CopyProperties( newItem, copy );//copy.Dupe( item, copy.Amount );
								copy.OnAfterDuped( newItem );
								newItem.Parent = null;

								if ( pack != null && !infel)
									pack.DropItem( newItem );
								else if(infel)
								{
									newItem.MoveToWorld( copy.Location, copy.Map==Map.Trammel ? Map.Felucca : Map.Trammel);
								}					
								else
									newItem.MoveToWorld( from.Location, from.Map );

								CommandLogging.WriteLine( from, "{0} {1} duped {2} creating {3}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( targ ), CommandLogging.Format( newItem ) );
							}
						}
						from.SendMessage( "Done" );
						done = true;
					}
					catch
					{
						from.SendMessage( "Error!" );
						return;
					}
				}

				if ( !done )
				{
					from.SendMessage( "Unable to dupe.  Item must have a 0 parameter constructor." );
				}
			}
		}

		private static void CopyProperties( Item dest, Item src )
		{
			
			if(src is BaseArmor || src is BaseClothing || src is BaseWeapon || src is BaseTalisman || src is Spellbook || src is BaseJewel || src is Quiver )
			{
				globalchangestone.CopyProperties(dest,src,false);				
			}
			else
			{
				PropertyInfo[] props = src.GetType().GetProperties();

				for ( int i = 0; i < props.Length; i++ )
				{
					try
					{
						if ( props[i].CanRead && props[i].CanWrite )
						{
							//Console.WriteLine( "Setting {0} = {1}", props[i].Name, props[i].GetValue( src, null ) );
							props[i].SetValue( dest, props[i].GetValue( src, null ), null );
						}
					}
					catch
					{
						//Console.WriteLine( "Denied" );
					}
				}  //OBSOLETED CODE
				
				
			}
			dest.InvalidateProperties();
		}
		
		
		public static Item DuplicateItem(Item source)
		{
		Type t = source.GetType();
		
		if(t==null)return null;
		
		ConstructorInfo c = t.GetConstructor( Type.EmptyTypes );
		
		if(c==null)return null;
		
		object o = c.Invoke( null );
			
		Item newItem = (Item)o;
		CopyProperties( newItem,source );
				
		if(newItem==null)return null;
		
		newItem.Parent = null;
		newItem.OnAfterDuped( newItem );			
		
		return newItem;
		}
		
		
		
		
		
	}
}
