using System;
using System.Collections.Generic;
using Server;
using Server.Items;
using Server.Misc;
using Server.Spells;
using Server.Spells.Third;
using Server.Spells.Sixth;
using Server.Targeting;
using Server.Engines.CannedEvil;

namespace Server.Mobiles
{
	public class TavaraSewel : BaseChampion
	{
		public override bool ClickTitle { get { return false; } }
		public override bool ShowFameTitle { get { return false; } }
		public override bool DeleteCorpseOnDeath { get { return true; } }
		public override bool CanRummageCorpses { get { return true; } }
		public override bool Uncalmable { get { return true; } }
		public override bool IsNotScaredOfDeath { get { return true; } } //neutika pri malem poctu hp
		public override ChampionSkullType SkullType { get { return ChampionSkullType.Greed; } }

		[Constructable]
		public TavaraSewel() : this (false, 3)
		{
		}

		[Constructable]
		public TavaraSewel(int range) : this (false, range)
		{
		}

		[Constructable]
		public TavaraSewel(bool ischampion, int range) : base(AIType.AI_Melee, FightMode.Closest, ischampion, range)
		{
			Title = "the Cursed";

			Hue = 0x8838;
			Female = true;
			Body = 0x191;
			Name = "Tavara Sewel";
			HairItemID = 0x203D;	//Pony Tail

			DropMin = 50;
			DropMax = 100;
			BonusLoot = "tokens";
			BonusLootAmount = Utility.RandomMinMax(15, 30);

			AddItem(new Kilt(0x59C));
			AddItem(new Sandals(0x599));

			Kryss kryss = new Kryss();
			Buckler buckler = new Buckler();
			RingmailGloves gloves = new RingmailGloves();
			FemalePlateChest chest = new FemalePlateChest();

			kryss.Hue = 0x96F;
			kryss.Movable = false;
			kryss.WeaponAttributes.HitHarm = 50;
			kryss.WeaponAttributes.HitLeechHits = 40;
			kryss.WeaponAttributes.HitLeechStam = 40;
			kryss.Attributes.AttackChance = 40;
			buckler.Hue = 0x96F; buckler.Movable = false;
			gloves.Hue = 0x599;
			chest.Hue = 0x96F;

			AddItem(kryss);
			AddItem(buckler);
			AddItem(gloves);
			AddItem(chest);

			SetStr(700, 720);
			SetDex(280, 300);
			SetInt(266, 305);

			SetHits(60000);
			SetMana(2500);
			SetStam(1000);

			SetDamage(25, 35);

			SetDamageType(ResistanceType.Poison, 70);
			SetDamageType(ResistanceType.Physical, 30);

			SetResistance(ResistanceType.Physical, 65, 75);
			SetResistance(ResistanceType.Fire, 65, 75);
			SetResistance(ResistanceType.Cold, 65, 75);
			SetResistance(ResistanceType.Poison, 65, 75);
			SetResistance(ResistanceType.Energy, 65, 75);

			SetSkill(SkillName.EvalInt, 77.6, 110.5);
			SetSkill(SkillName.Necromancy, 120.6, 130.5);
			SetSkill(SkillName.SpiritSpeak, 120.1, 150.5);
			SetSkill(SkillName.Magery, 90.1, 120.1);
			SetSkill(SkillName.Poisoning, 80.5);
			SetSkill(SkillName.Meditation, 110.0);
			SetSkill(SkillName.MagicResist, 80.1, 85.0);
			SetSkill(SkillName.Parry, 90.1, 100.1);
			SetSkill(SkillName.Tactics, 120.0);
			SetSkill(SkillName.Anatomy, 100.0);
			SetSkill(SkillName.Wrestling, 90.1, 120.0);
			SetSkill(SkillName.Fencing, 115.1, 120.0);

			Fame = 10000;
			Karma = -15000;

			VirtualArmor = 65;

			m_Change = DateTime.Now;
			m_Stomp = DateTime.Now;

			if(0.05 > Utility.RandomDouble())
				PackItem((Item)Activator.CreateInstance(KhalAnkur.ExtraLoot[Utility.Random(KhalAnkur.ExtraLoot.Length)]));
		}

		public override int GetIdleSound()
		{
			return 0x27F;
		}

		public override int GetAngerSound()
		{
			return 0x258;
		}

		public override int GetDeathSound()
		{
			return 0x25B;
		}

		public override int GetHurtSound()
		{
			return 0x257;
		}

		public override bool OnBeforeDeath()
		{
			if (!base.OnBeforeDeath())
				return false;

			Server.Regions.KhaldunRegion.DropHealthOrb(this);

			BaseBook journal = Loot.RandomTavarasJournal();
			journal.MoveToWorld(Location, Map);

			Container pack = this.Backpack;
			if (pack != null)
			{
				pack.Movable = true;
				pack.MoveToWorld(Location, Map);
			}

			Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1);
			return true;
		}

		public override void OnKilledBy(Mobile mob)
		{
			base.OnKilledBy(mob);

			if (mob.Talisman is KhalAnkurAmulet)
			{
				((KhalAnkurAmulet) mob.Talisman).SpendingPoints += 3;
			}

			if (Teragon.CheckArtifactChance(mob, this))
				Teragon.GiveArtifactTo(mob, this);
		}

		public override bool AlwaysMurderer { get { return true; } }

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

		public virtual int StrikingRange { get { return 12; } }

		public override void OnThink()
		{
			base.OnThink();

			if (Combatant != null)
			{
				if (m_Change < DateTime.Now && Utility.RandomDouble() < 0.2)
					ChangeOpponent();

				if (m_Stomp < DateTime.Now && Utility.RandomDouble() < 0.1)
					HoofStomp();
			}

			// exit ilsh 1313, 936, 32
		}

		public override void Damage(int amount, Mobile from)
		{
			base.Damage(amount, from);

			if (Combatant == null || Hits > HitsMax * 0.5 || Utility.RandomDouble() > 0.01)
				return;

			new InvisibilitySpell(this, null).Cast();

			Target target = Target;

			if (target != null)
				target.Invoke(this, this);

			Timer.DelayCall(TimeSpan.FromSeconds(2), new TimerCallback(Teleport));
		}

		public override void OnDamage(int amount, Mobile from, bool willKill, int typ)
		{
			if (typ == 2 && from != null)
			{
				AOS.Damage(from, this, amount / 2, 50, 0, 0, 0, 50);
				amount = 0;
			}

			base.OnDamage(amount, from, willKill, typ);
		}

		public override WeaponAbility GetWeaponAbility()
		{
			switch (Utility.Random(3))
			{
				default:
					case 0: return WeaponAbility.DoubleStrike;
				case 1: return WeaponAbility.WhirlwindAttack;
				case 2: return WeaponAbility.BleedAttack;
			}
		}

		public override bool Unprovokable { get { return true; } }
		public override bool BardImmune { get { return true; } }
		public override Poison PoisonImmune { get { return Poison.Lethal; } }
		public override int TreasureMapLevel { get { return 5; } }

		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();

			m_Change = DateTime.Now;
			m_Stomp = DateTime.Now;
		}

		private DateTime m_Change;
		private DateTime m_Stomp;

		public static Point3D GetSpawnPosition(Point3D from, Map map, int range)
		{
			if (map == null)
				return from;

			for (int i = 0; i < 10; i ++)
			{
				int x = from.X + Utility.Random(range);
				int y = from.Y + Utility.Random(range);
				int z = map.GetAverageZ(x, y);

				if (Utility.RandomBool())
					x *= -1;

				if (Utility.RandomBool())
					y *= -1;

				Point3D p = new Point3D(x, y, from.Z);

				if (map.CanSpawnMobile(p) && map.LineOfSight(from, p))
					return p;

				p = new Point3D(x, y, z);

				if (map.CanSpawnMobile(p) && map.LineOfSight(from, p))
					return p;
			}

			return from;
		}

		public void Teleport()
		{
			// 20 tries to teleport
			for (int tries = 0; tries < 20; tries ++)
			{
				int x = Utility.RandomMinMax(5, 7);
				int y = Utility.RandomMinMax(5, 7);

				if (Utility.RandomBool())
					x *= -1;

				if (Utility.RandomBool())
					y *= -1;

				Point3D p = new Point3D(X + x, Y + y, 0);
				IPoint3D po = new LandTarget(p, Map) as IPoint3D;

				if (po == null)
					continue;

				SpellHelper.GetSurfaceTop(ref po);

				if (InRange(p, 12) && InLOS(p) && Map.CanSpawnMobile(po.X, po.Y, po.Z))
				{
					Point3D from = Location;
					Point3D to = new Point3D(po);

					Location = to;
					ProcessDelta();

					FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
					PlaySound(0x1FE);

					break;
				}
			}

			RevealingAction();
		}

		public void ChangeOpponent()
		{
			Mobile agro, best = null;
			double distance, random = Utility.RandomDouble();

			if (random < 0.75)
			{
				// find random target relatively close
				for (int i = 0; i < Aggressors.Count && best == null; i ++)
				{
					agro = Validate(Aggressors[ i ].Attacker);

					if (agro == null)
						continue;

					distance = StrikingRange - GetDistanceToSqrt(agro);

					if (distance > 0 && distance < StrikingRange - 2 && InLOS(agro.Location))
					{
						distance /= StrikingRange;

						if (random < distance)
							best = agro;
					}
				}
			}
			else
			{
				int damage = 0;

				// find a player who dealt most damage
				for (int i = 0; i < DamageEntries.Count; i ++)
				{
					agro = Validate(DamageEntries[ i ].Damager);

					if (agro == null)
						continue;

					distance = GetDistanceToSqrt(agro);

					if (distance < StrikingRange && DamageEntries[ i ].DamageGiven > damage && InLOS(agro.Location))
					{
						best = agro;
						damage = DamageEntries[ i ].DamageGiven;
					}
				}
			}

			if (best != null)
			{
				// teleport
				best.Location = GetSpawnPosition(Location, Map, 1);
				best.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
				best.PlaySound(0x1FE);

				if (!best.Poisoned)
					Timer.DelayCall(TimeSpan.FromSeconds(1), new TimerCallback(delegate()
					{
						// poison
					                                                              	best.ApplyPoison(this, Poison.Lethal);
				best.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist);
				best.PlaySound(0x474);
			}

));

			m_Change = DateTime.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10));
		}
	}

	public void HoofStomp()
	{
		foreach (Mobile m in GetMobilesInRange(StrikingRange))
		{
			Mobile valid = Validate(m);

			if (valid != null && Affect(valid))
			{ }
			// 					valid.SendLocalizedMessage( 1075081 ); // *Dreadhorns eyes light up, his mouth almost a grin, as he slams one hoof to the ground!*
		}

		// earthquake
			PlaySound(0x2F3);

		Timer.DelayCall(TimeSpan.FromSeconds(30), new TimerCallback(delegate { StopAffecting(); }));

		m_Stomp = DateTime.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(40, 50));
	}

	public Mobile Validate(Mobile m)
	{
		Mobile agro;

		if (m is BaseCreature)
			agro = ((BaseCreature) m).ControlMaster;
			else
				agro = m;

			if (!CanBeHarmful(agro, false) || !agro.Player/* || Combatant == agro*/)
				return null;

		return agro;
	}

	private static Dictionary<Mobile, bool> m_Affected;

	public static bool IsUnderInfluence(Mobile mobile)
	{
		if (m_Affected != null)
		{
			if (m_Affected.ContainsKey(mobile))
				return true;
			}

			return false;
		}

		public static bool Affect(Mobile mobile)
		{
			if (m_Affected == null)
				m_Affected = new Dictionary<Mobile, bool>();

			if (!m_Affected.ContainsKey(mobile))
			{
				m_Affected.Add(mobile, true);
				return true;
			}

			return false;
		}

		public static void StopAffecting()
		{
			if (m_Affected != null)
				m_Affected.Clear();
		}
	}
}