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

namespace Server.Items
{
	[FlipableAttribute( 0x100A/*East*/, 0x100B/*South*/ )]
	public class ArcheryButte : AddonComponent
	{
		private double m_MinSkill;
		private double m_MaxSkill;

		private int m_Arrows, m_Bolts;
		private bool m_Event;

		private DateTime m_LastUse;
		
		[CommandProperty( AccessLevel.GameMaster )]
		public double MinSkill
		{
			get{ return m_MinSkill; }
			set{ m_MinSkill = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public double MaxSkill
		{
			get{ return m_MaxSkill; }
			set{ m_MaxSkill = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public DateTime LastUse
		{
			get{ return m_LastUse; }
			set{ m_LastUse = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public bool FacingEast
		{
			get{ return ( ItemID == 0x100A ); }
			set{ ItemID = value ? 0x100A : 0x100B; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Arrows
		{
			get{ return m_Arrows; }
			set{ m_Arrows = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public int Bolts
		{
			get{ return m_Bolts; }
			set{ m_Bolts = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public bool Event
		{
			get{ return m_Event; }
			set
         {
            m_Event = value;
            
            if ( m_Event )
            {
               m_Bolts = 0;
               m_Arrows = 0;
               m_Entries = null;
            }
         }
		}

		[Constructable]
		public ArcheryButte() : this( 0x100A )
		{
		}

		public ArcheryButte( int itemID ) : base( itemID )
		{
			m_MinSkill = -25.0;
			m_MaxSkill = +25.0;
			m_Event = false;
		}

		public ArcheryButte( Serial serial ) : base( serial )
		{
		}

		public override void OnDoubleClick( Mobile from )
		{
			if ( from.InRange( GetWorldLocation(), 1 ) )
			{
            if ( m_Event && from.AccessLevel > AccessLevel.Player ) //GM Gump
            {
               from.CloseGump(typeof(ArcheryButteGump));
					from.SendGump( new ArcheryButteGump( from ) );
            }
            else if ( m_Arrows > 0 || m_Bolts > 0 )
               Gather( from );
         }
			else
				Fire( from );
		}

		public void Gather( Mobile from )
		{
			from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500592 ); // You gather the arrows and bolts.

			if ( m_Arrows > 0 )
				from.AddToBackpack( new Arrow( m_Arrows ) );

			if ( m_Bolts > 0 )
				from.AddToBackpack( new Bolt( m_Bolts ) );

			m_Arrows = 0;
			m_Bolts = 0;

			m_Entries = null;
		}

		private static TimeSpan UseDelay = TimeSpan.FromSeconds( 2.0 );

		private class ScoreEntry
		{
			private int m_Total;
			private int m_Count;

			public int Total{ get{ return m_Total; } set{ m_Total = value; } }
			public int Count{ get{ return m_Count; } set{ m_Count = value; } }

			public void Record( int score )
			{
				m_Total += score;
				m_Count += 1;
			}

			public ScoreEntry()
			{
			}
		}

		private Hashtable m_Entries;

		private ScoreEntry GetEntryFor( Mobile from )
		{
			if ( m_Entries == null )
				m_Entries = new Hashtable();

			ScoreEntry e = (ScoreEntry)m_Entries[from];

			if ( e == null )
				m_Entries[from] = e = new ScoreEntry();

			return e;
		}

		public void Fire( Mobile from )
		{
			BaseRanged bow = from.Weapon as BaseRanged;

			if ( bow == null )
			{
				SendLocalizedMessageTo( from, 500593 ); // You must practice with ranged weapons on this.
				return;
			}

			if ( DateTime.Now < (m_LastUse + UseDelay) )
				return;

			Point3D worldLoc = GetWorldLocation();

			if ( FacingEast ? from.X <= worldLoc.X : from.Y <= worldLoc.Y )
			{
				from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500596 ); // You would do better to stand in front of the archery butte.
				return;
			}

			if ( FacingEast ? from.Y != worldLoc.Y : from.X != worldLoc.X )
			{
				from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500597 ); // You aren't properly lined up with the archery butte to get an accurate shot.
				return;
			}

			if ( !from.InRange( worldLoc, 6 ) )
			{
				from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500598 ); // You are too far away from the archery butte to get an accurate shot.
				return;
			}
			else if ( from.InRange( worldLoc, 4 ) )
			{
				from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500599 ); // You are too close to the target.
				return;
			}

			Container pack = from.Backpack;
			Type ammoType = bow.AmmoType;

			bool isArrow = ( ammoType == typeof( Arrow ) );
			bool isBolt = ( ammoType == typeof( Bolt ) );
			bool isKnown = ( isArrow || isBolt );

			if ( pack == null || !pack.ConsumeTotal( ammoType, 1 ) )
			{
				if ( isArrow )
					from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500594 ); // You do not have any arrows with which to practice.
				else if ( isBolt )
					from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500595 ); // You do not have any crossbow bolts with which to practice.
				else
					SendLocalizedMessageTo( from, 500593 ); // You must practice with ranged weapons on this.

				return;
			}

			m_LastUse = DateTime.Now;

			from.Direction = from.GetDirectionTo( GetWorldLocation() );
			bow.PlaySwingAnimation( from );
			from.MovingEffect( this, bow.EffectID, 18, 1, false, false );

			ScoreEntry se = GetEntryFor( from );

			if ( !m_Event && !from.CheckSkill( bow.Skill, m_MinSkill, m_MaxSkill ) )
			{
				from.PlaySound( bow.MissSound );

				PublicOverheadMessage( MessageType.Regular, 0x3B2, 500604, from.Name ); // You miss the target altogether.

				se.Record( 0 );

				if ( se.Count == 1 )
					PublicOverheadMessage( MessageType.Regular, 0x3B2, 1062719, se.Total.ToString() );
				else
					PublicOverheadMessage( MessageType.Regular, 0x3B2, 1042683, String.Format( "{0}\t{1}", se.Total, se.Count ) );

				return;
			}

			Effects.PlaySound( Location, Map, 0x2B1 );

			double rand = Utility.RandomDouble();

			int area, score, splitScore;

			if ( 0.10 > rand )
			{
				area = 0; // bullseye
				score = 50;
				splitScore = 100;
			}
			else if ( 0.25 > rand )
			{
				area = 1; // inner ring
				score = 10;
				splitScore = 20;
			}
			else if ( 0.50 > rand )
			{
				area = 2; // middle ring
				score = 5;
				splitScore = 15;
			}
			else
			{
				area = 3; // outer ring
				score = 2;
				splitScore = 5;
			}

			bool split = ( isKnown && 0.2 > Utility.RandomDouble() );

			if ( split )
			{
				PublicOverheadMessage( MessageType.Regular, 0x3B2, 1010027 + (isArrow ? 0 : 4) + area, from.Name );
			}
			else
			{
				PublicOverheadMessage( MessageType.Regular, 0x3B2, 1010035 + area, from.Name );

				if ( !m_Event )
				{
               if ( isArrow )
    					++m_Arrows;
    				else if ( isBolt )
    					++m_Bolts;
            }
			}

			se.Record( split ? splitScore : score );

// 			if ( se.Count == 1 )
// 				PublicOverheadMessage( MessageType.Regular, 0x3B2, 1062719, se.Total.ToString() );
// 			else if ( se.Count == 10 )
// 				PublicOverheadMessage( MessageType.Regular, 0x3F, 1042683, String.Format( "{0}\t{1}", se.Total, se.Count ) );
// 			else
// 				PublicOverheadMessage( MessageType.Regular, 0x3B2, 1042683, String.Format( "{0}\t{1}", se.Total, se.Count ) );

			if ( se.Count == 1 )
				PublicOverheadMessage( MessageType.Regular, 696, false, String.Format( "{0}: {1} bodu po prvni strele", from.RawName, se.Total ) );
			else if ( se.Count == 10 )
			{
				PublicOverheadMessage( MessageType.Regular, 0x3F, false, String.Format( "{0}: {1} bodu za 10 strel", from.RawName, se.Total ) );
				
				if ( m_Event )
				{
               //Zapis do gumpu
      			ArcheryButteLog.Record( se.Total, from );               
               m_Entries.Remove( from );
            }
         }
			else
				PublicOverheadMessage( MessageType.Regular, 696, false, String.Format( "{0}: {1} bodu za {2} strel{3}", from.RawName, se.Total, se.Count, (se.Count < 5) ? "y" : "" ) );
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );

			writer.Write( (int) 1 );
			
			writer.Write( m_Event );

			writer.Write( m_MinSkill );
			writer.Write( m_MaxSkill );
			writer.Write( m_Arrows );
			writer.Write( m_Bolts );
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadInt();

			switch ( version )
			{
				case 1:
				{
      			m_Event = reader.ReadBool();
					goto case 0;
				}
            case 0:
				{
					m_MinSkill = reader.ReadDouble();
					m_MaxSkill = reader.ReadDouble();
					m_Arrows = reader.ReadInt();
					m_Bolts = reader.ReadInt();

					if ( !m_Event && ( m_MinSkill == 0.0 && m_MaxSkill == 30.0 ) )
					{
						m_MinSkill = -25.0;
						m_MaxSkill = +25.0;
					}

					break;
				}
			}
		}		
		
		private class ArcheryButteGump : Gump
		{
			private ArrayList scorelist;
         
         public ArcheryButteGump( Mobile from ) : base(100, 60)
			{
//290 backgroud y
            scorelist = ArcheryButteLog.GetSortedData();
            string str = "";
            
            if ( scorelist == null || scorelist.Count < 1 )
               str = "Zadna data";
            else
            {
            	foreach ( KeyValuePair<Mobile, int> kv in scorelist )
            	{
                  str += String.Format( "{0}. {1}<br>", kv.Value, ((Mobile)kv.Key).RawName );
            	}
            }
            
            this.Closable=true;
            this.Disposable=true;
            this.Dragable=true;
            this.Resizable=false;
            this.AddPage(0);
            
            this.AddBackground(0, 0, 237, 338, 9200);
            this.AddHtml( 5, 25, 225, 255, str, (bool)true, (bool)true);
            this.AddLabel(64, 3, 1152, @"Archery Event");
            this.AddButton(200, 310, 4005, 4007, (int)Buttons.ReloadGump, GumpButtonType.Reply, 0);
            this.AddButton(10, 310, 4002, 4004, (int)Buttons.ResetStats, GumpButtonType.Reply, 0);
            this.AddButton(10, 285, 4029, 4031, (int)Buttons.Award, GumpButtonType.Reply, 0);
            this.AddLabel(45, 287, 0, @"Vysledky a odmeny");
            this.AddLabel(45, 312, 0, @"Vymazat");
            this.AddLabel(143, 312, 0, @"Refresh");
         }
			
        public enum Buttons
        {
            Cancel,
            ReloadGump,
            ResetStats,
            Award
        }			

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

				if ( from == null )
					return;
					
            switch( info.ButtonID )
    			{
    				case (int)Buttons.ReloadGump:
    					{
                     from.CloseGump(typeof(ArcheryButteGump));
                     from.SendGump( new ArcheryButteGump( from ) );
    					}
    					break;
    				case (int)Buttons.ResetStats:
    					{
                     if ( from.AccessLevel < AccessLevel.GameMaster )
                        return;
                     
                     ArcheryButteLog.Reset();
                     from.CloseGump(typeof(ArcheryButteGump));
                     from.SendGump( new ArcheryButteGump( from ) );
                     from.SendMessage("Vysledkova listina byla vymazana");
    					}
    					break;
    				case (int)Buttons.Award:
    					{
                     if ( from.AccessLevel < AccessLevel.GameMaster )
                        return;
                     
                     if ( scorelist == null || scorelist.Count < 1 )
                     {
                        from.SendMessage("Zadni hraci pro rozdani odmen");
                     }
                     else
                     {
                        World.Broadcast( 192, false, "Vysledky lukostrelby:" );
                        KeyValuePair<Mobile, int> player;
                        ArrayList toDelete = new ArrayList();
                        
                        string lukName = @"<bodytextblue><big><center>Putovni luk za vitezstvi v lukostrelbe";
                        string toulecName = @"<bodytextblue><big><center>Putovni toulec za 2. misto v lukostrelbe";
                        string talismanName = @"<bodytextblue><big><center>Putovni talisman za 3. misto v lukostrelbe";
                        
                        //Smazat stare odmeny
                        foreach ( Item item in World.Items.Values )
                        {
                           if ( item is Luk && item.Name == lukName ) //0x40426A09 Seriove cislo luku
                              toDelete.Add( item );
                           else if ( item is ElvenQuiver && item.Name == toulecName )
                              toDelete.Add( item );
                           else if ( item is BirdsofBritanniaTalisman && item.Name == talismanName )
                              toDelete.Add( item );
                        }
                        
                        foreach ( Item it in toDelete )
				              it.Delete();
                        
                        for ( int i = 0; i < scorelist.Count; ++i )
                        {
                           player = (KeyValuePair<Mobile, int>) scorelist[i];
                           
                           if ( !( player.Key is Mobile ) )
                                 continue;
                                 
                           if ( i == 0 ) //1. misto
                           {
                              World.Broadcast( 192, false, "1. misto {0} - {1} bodu", player.Key.RawName, player.Value );
                              player.Key.AddToBackpack( new CechovniMince( player.Value ) );
                              
                              Item vlajka = new Item( 5594 );
                              vlajka.Movable = true;
                              vlajka.Name = String.Format( "Hraci {0} za prvni misto v lukostrelbe {1:D}", player.Key.RawName, DateTime.Today );
                              player.Key.AddToBackpack( vlajka );
                              
                              Luk luk = new Luk();
                              luk.Name = lukName;
                              luk.Hue = 2538;
                              luk.WeaponAttributes.SelfRepair = 10;
                              luk.WeaponAttributes.HitFireball = 35;
                              luk.BlessedFor = player.Key;
                              Server.Engines.XmlSpawner2.XmlAttach.AttachTo( (BaseWeapon) luk, new Server.Engines.XmlSpawner2.XmlEnchantWeaponDamage( 5 ) );
                              player.Key.AddToBackpack( luk );

                              player.Key.SendMessage("Odmena byla umistena do tveho batohu. Gratulujeme!");
                           }
                           else if ( i == 1 ) //2. misto
                           {
                              World.Broadcast( 192, false, "2. misto {0} - {1} bodu", player.Key.RawName, player.Value );
                              player.Key.AddToBackpack( new CechovniMince( player.Value ) );

                              BaseQuiver toulec = new ElvenQuiver();
                              toulec.Name = toulecName;
                              toulec.Hue = 2538;
                              toulec.LowerAmmoCost = 100;
                              toulec.MaxAmmo = 50;
                              toulec.ItemID = 0x2B03;
                        		toulec.Attributes.WeaponSpeed = 20;
                        		toulec.Attributes.WeaponDamage = 25;
                        		toulec.Attributes.AttackChance = 30;
                        		toulec.Attributes.BonusDex = 10;
                              toulec.SkillBonuses.SetValues( 0, SkillName.Archery, 15.0 );
                              toulec.SkillBonuses.SetValues( 1, SkillName.Tactics, 15.0 );
                              toulec.BlessedFor = player.Key;
                              player.Key.AddToBackpack( toulec );
                              
                              player.Key.SendMessage("Odmena byla umistena do tveho batohu. Gratulujeme!");
                           }
                           else if ( i == 2 ) //3. misto
                           {
                              World.Broadcast( 192, false, "3. misto {0} - {1} bodu", player.Key.RawName, player.Value );
                              player.Key.AddToBackpack( new CechovniMince( player.Value ) );
                              
                              BaseTalisman talisman = new BirdsofBritanniaTalisman();
                              talisman.Name = talismanName;
                              talisman.Hue = 2538;
                              talisman.Protection = new TalismanAttribute( typeof( DaemonicRoach ), 50, "Daemonic Roach" );
                              talisman.Blessed = false;
                              talisman.Killer = new TalismanAttribute( typeof( ElderTreefellow ), 50, "Elder Treefellow" );
                        		talisman.Attributes.Luck = 200;
                        		talisman.Attributes.WeaponDamage = 15;
                        		talisman.Attributes.AttackChance = 20;
                        		talisman.Attributes.BonusDex = 5;
                                                      		
                      			talisman.MaxChargeTime = 1800;
                      			talisman.MaxCharges = 30;
                      			talisman.Charges = talisman.MaxCharges;
                      			talisman.Summoner = new TalismanAttribute( typeof( Arrow ), 100, 1023904 );
                      			
                      			talisman.Skill = SkillName.Fletching;
                      			talisman.SuccessBonus = 20;
                        		
                              talisman.SkillBonuses.SetValues( 0, SkillName.Archery, 10.0 );
                              talisman.SkillBonuses.SetValues( 1, SkillName.Tactics, 10.0 );
                              talisman.BlessedFor = player.Key;
                              player.Key.AddToBackpack( talisman );
                              
                              player.Key.SendMessage("Odmena byla umistena do tveho batohu. Gratulujeme!");
                           }
                           
                           player.Key.AddToBackpack( new TokenCheck( player.Value ) );
                           player.Key.SendMessage("Na turnaji v lukostrelbe jsi ziskal{0} {1} bodu a obsadil{0} {2}. misto", (player.Key.Female) ? "a" : "", player.Value, i + 1 );
                        }
                        
                        from.SendMessage("Odmeny rozdany");
                     }
                    
                     from.CloseGump(typeof(ArcheryButteGump));
                     from.SendGump( new ArcheryButteGump( from ) );
    					}
    					break;
    				case (int)Buttons.Cancel:
    					{
    					}
    					break;
    			}
    		}
		}
	}

	public class ArcheryButteAddon : BaseAddon
	{
		public override BaseAddonDeed Deed{ get{ return new ArcheryButteDeed(); } }

		[Constructable]
		public ArcheryButteAddon()
		{
			AddComponent( new ArcheryButte( 0x100A ), 0, 0, 0 );
		}

		public ArcheryButteAddon( Serial serial ) : base( serial )
		{
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );

			writer.Write( (int) 0 ); // version
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadInt();
		}
	}

	public class ArcheryButteDeed : BaseAddonDeed
	{
		public override BaseAddon Addon{ get{ return new ArcheryButteAddon(); } }
		public override int LabelNumber{ get{ return 1024106; } } // archery butte

		[Constructable]
		public ArcheryButteDeed()
		{
		}

		public ArcheryButteDeed( Serial serial ) : base( serial )
		{
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );

			writer.Write( (int) 0 ); // version
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadInt();
		}
	}
}