using System;
using Server.Network;
using Server.Prompts;
using Server.Multis;
using Server.Regions;

namespace Server.Items
{
	[FlipableAttribute(0x1f14, 0x1f15, 0x1f16, 0x1f17)]
	public class RecallRune : Item
	{
		private string m_Description;
		private bool m_Marked;
		private Point3D m_Target;
		private Map m_TargetMap;
		private BaseHouse m_House;

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

			if (m_House != null && !m_House.Deleted)
			{
				writer.Write((int) 1); // version

				writer.Write((Item) m_House);
			}
			else
			{
				writer.Write((int) 0); // version
			}

			writer.Write((string) m_Description);
			writer.Write((bool) m_Marked);
			writer.Write((Point3D) m_Target);
			writer.Write((Map) m_TargetMap);
		}

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

			int version = reader.ReadInt();

			switch (version)
			{
				case 1:
				{
					m_House = reader.ReadItem() as BaseHouse;
					goto case 0;
				}

				case 0:
				{
					m_Description = reader.ReadString();
					m_Marked = reader.ReadBool();
					m_Target = reader.ReadPoint3D();
					m_TargetMap = reader.ReadMap();

					CalculateHue();

					break;
				}
			}

			if (m_TargetMap == Map.Underworld)
			{
				if (this.Map != Map.Underworld)
					this.Delete();
				else
					this.LootType = LootType.Newbied;
			}
		}

		[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
		public BaseHouse House
		{
			get
			{
				if (m_House != null && m_House.Deleted)
					House = null;

				return m_House;
			}

			set { m_House = value; CalculateHue(); InvalidateProperties(); }
		}

		[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
		public string Description
		{
			get
			{
				return m_Description;
			}

			set
			{
				m_Description = value;
				InvalidateProperties();
			}
		}

		[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
		public bool Marked
		{
			get
			{
				return m_Marked;
			}

			set
			{
				if (m_Marked != value)
				{
					m_Marked = value;
					CalculateHue();
					InvalidateProperties();
				}
			}
		}

		[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
		public Point3D Target
		{
			get
			{
				return m_Target;
			}

			set
			{
				m_Target = value;
			}
		}

		[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
		public Map TargetMap
		{
			get
			{
				return m_TargetMap;
			}

			set
			{
				if (m_TargetMap != value)
				{
					m_TargetMap = value;
					CalculateHue();

					InvalidateProperties();
				}
			}
		}

		private void CalculateHue()
		{
			if (!m_Marked)
				Hue = 0;
			else if (m_TargetMap == Map.Trammel)
				Hue = (House != null ? 0x47F : 50);
			else if (m_TargetMap == Map.Felucca)
				Hue = (House != null ? 0x66D : 0);
			else if (m_TargetMap == Map.Ilshenar)
				Hue = (House != null ? 0x55F : 1102);
			else if (m_TargetMap == Map.Malas)
				Hue = (House != null ? 0x55F : 1102);
			else if (m_TargetMap == Map.Tokuno)
				Hue = (House != null ? 0x47F : 1154);
			else if (m_TargetMap == Map.Underworld)
				Hue = 1081;
		}

		public void Mark(Mobile m)
		{
			m_Marked = true;

			bool setDesc = false;
			if (Core.AOS)
			{
				m_House = BaseHouse.FindHouseAt(m);

				if (m_House == null)
				{
					m_Target = m.Location;
					m_TargetMap = m.Map;
				}
				else
				{
					HouseSign sign = m_House.Sign;

					if (sign != null)
						m_Description = sign.Name;
					else
						m_Description = null;

					if (m_Description == null || (m_Description = m_Description.Trim()).Length == 0)
						m_Description = "an unnamed house";

					setDesc = true;

					int x = m_House.BanLocation.X;
					int y = m_House.BanLocation.Y + 2;
					int z = m_House.BanLocation.Z;

					Map map = m_House.Map;

					if (map != null && !map.CanFit(x, y, z, 16, false, false))
						z = map.GetAverageZ(x, y);

					m_Target = new Point3D(x, y, z);
					m_TargetMap = map;
				}
			}
			else
			{
				m_House = null;
				m_Target = m.Location;
				m_TargetMap = m.Map;
			}

			if(!setDesc)
				m_Description = BaseRegion.GetRuneNameFor(Region.Find(m_Target, m_TargetMap));

			CalculateHue();
			InvalidateProperties();
		}

		private const string RuneFormat = "a recall rune for {0}";

		public override void GetProperties(ObjectPropertyList list)
		{
			base.GetProperties(list);

			if (m_Marked)
			{
				string desc;

				if ((desc = m_Description) == null || (desc = desc.Trim()).Length == 0)
					desc = "an unknown location";

				if (m_TargetMap == Map.Tokuno)
					list.Add((House != null ? 1063260 : 1063259), RuneFormat, desc); // ~1_val~ (Tokuno Islands)[(House)]
				else if (m_TargetMap == Map.Malas)
					list.Add((House != null ? 1062454 : 1060804), RuneFormat, desc); // ~1_val~ (Malas)[(House)]
				else if (m_TargetMap == Map.Felucca)
					list.Add((House != null ? 1062452 : 1060805), RuneFormat, desc); // ~1_val~ (Felucca)[(House)]
				else if (m_TargetMap == Map.Trammel)
					list.Add((House != null ? 1062453 : 1060806), RuneFormat, desc); // ~1_val~ (Trammel)[(House)]
				else
					list.Add((House != null ? "{0} ({1})(House)" : "{0} ({1})"), String.Format(RuneFormat, desc), m_TargetMap);
			}
		}

		public override void OnSingleClick(Mobile from)
		{
			if (m_Marked)
			{
				string desc;

				if ((desc = m_Description) == null || (desc = desc.Trim()).Length == 0)
					desc = "an unknown location";

				if (m_TargetMap == Map.Tokuno)
					LabelTo(from, (House != null ? 1063260 : 1063259), String.Format(RuneFormat, desc)); // ~1_val~ (Tokuno Islands)[(House)]
				else if (m_TargetMap == Map.Malas)
					LabelTo(from, (House != null ? 1062454 : 1060804), String.Format(RuneFormat, desc)); // ~1_val~ (Malas)[(House)]
				else if (m_TargetMap == Map.Felucca)
					LabelTo(from, (House != null ? 1062452 : 1060805), String.Format(RuneFormat, desc)); // ~1_val~ (Felucca)[(House)]
				else if (m_TargetMap == Map.Trammel)
					LabelTo(from, (House != null ? 1062453 : 1060806), String.Format(RuneFormat, desc)); // ~1_val~ (Trammel)[(House)]
				else
					LabelTo(from, (House != null ? "{0} ({1})(House)" : "{0} ({1})"), String.Format(RuneFormat, desc), m_TargetMap);
			}
			else
			{
				LabelTo(from, "an unmarked recall rune");
			}
		}

		public override void OnDoubleClick(Mobile from)
		{
			int number;

			if (!IsChildOf(from.Backpack))
			{
				number = 1042001; // That must be in your pack for you to use it.
			}
			else if (House != null)
			{
				number = 1062399; // You cannot edit the description for this rune.
			}
			else if (m_Marked)
			{
				number = 501804; // Please enter a description for this marked object.

				from.Prompt = new RenamePrompt(this);
			}
			else
			{
				number = 501805; // That rune is not yet marked.
			}

			from.SendLocalizedMessage(number);
		}

		private class RenamePrompt : Prompt
		{
			private RecallRune m_Rune;

			public RenamePrompt(RecallRune rune)
			{
				m_Rune = rune;
			}

			public override void OnResponse(Mobile from, string text)
			{
				if (m_Rune.House == null && m_Rune.Marked)
				{
					m_Rune.Description = text;
					from.SendLocalizedMessage(1010474); // The etching on the rune has been changed.
				}
			}
		}
		
		[Constructable]
		public RecallRune(bool map) : base(0x1F14)
		{
			Weight = 0.1;
			TargetMap = Map.Underworld;
			Target = new Point3D( 4683, 1424, 0 );
			Marked = true;
			Description = "Zakladna Underworld";
			LootType = LootType.Blessed;
			// CalculateHue();
		}

		[Constructable]
		public RecallRune() : base(0x1F14)
		{
			Weight = 1.0;
			CalculateHue();
		}

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