/
etc/
lib/
src/Abilities/
src/Abilities/Skills/
src/Abilities/Spells/
src/Abilities/Spells/Enums/
src/Affects/
src/ArtheaConsole/
src/ArtheaConsole/Properties/
src/ArtheaGUI/Properties/
src/Clans/Enums/
src/Commands/Communication/
src/Commands/ItemCommands/
src/Connections/
src/Connections/Colors/
src/Connections/Enums/
src/Connections/Players/
src/Connections/Players/Enums/
src/Continents/
src/Continents/Areas/
src/Continents/Areas/Characters/
src/Continents/Areas/Characters/Enums/
src/Continents/Areas/Items/
src/Continents/Areas/Items/Enums/
src/Continents/Areas/Rooms/
src/Continents/Areas/Rooms/Enums/
src/Continents/Areas/Rooms/Exits/
src/Creation/
src/Creation/Attributes/
src/Creation/Interfaces/
src/Database/
src/Database/Interfaces/
src/Environment/
src/Properties/
src/Scripts/Enums/
src/Scripts/Interfaces/
#region Arthea License

/***********************************************************************
*  Arthea MUD by R. Jennings (2007)      http://arthea.googlecode.com/ *
*  By using this code you comply with the Artistic and GPLv2 Licenses. *
***********************************************************************/

#endregion

using System.Xml.Serialization;
using Arthea.Affects;
using Arthea.Continents.Areas.Characters;
using Arthea.Continents.Areas.Items.Enums;
using Arthea.Continents.Areas.Rooms;
using Arthea.Creation.Attributes;
using Arthea.Environment;
using Arthea.Interfaces;
using Arthea.Scripts;

namespace Arthea.Continents.Areas.Items
{
    /// <summary>
    /// Implements an item
    /// </summary>
    public class Item : Scriptable
    {
        #region [rgn] Fields (10)

        private AffectList affects = new AffectList();
        private Character carriedBy;
        [EditIgnore] private ItemList contents = new ItemList();
        [EditShow] private ItemIndex index;
        [XmlIgnore] private Room inRoom;
        [EditIgnore] private Item inside;
        private string name;
        private string roomDescr;
        private string shortDescr;
        private WearLocation wearLocation = WearLocation.None;

        #endregion [rgn]

        #region [rgn] Constructors (2)

        /// <summary>
        /// Initializes a new instance of the <see cref="Item"/> class.
        /// </summary>
        /// <param name="item">The item.</param>
        public Item(ItemIndex item)
        {
            index = item;
            name = item.Name;
            shortDescr = item.ShortDescr;
            roomDescr = item.RoomDescr;
            affects = item.Affects;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Item"/> class.
        /// </summary>
        public Item()
        {
        }

        #endregion [rgn]

        #region [rgn] Properties (14)

        /// <summary>
        /// Gets or sets the affects.
        /// </summary>
        /// <value>The affects.</value>
        public AffectList Affects
        {
            get { return affects; }
            set { affects = value; }
        }

        /// <summary>
        /// Gets or sets the carried by.
        /// </summary>
        /// <value>The carried by.</value>
        [XmlIgnore]
        public Character CarriedBy
        {
            get { return carriedBy; }
            set
            {
                if (value != null)
                {
                    value.Carrying.Add(this);
                }
                else if (carriedBy != null)
                {
                    carriedBy.Carrying.Remove(this);
                }

                carriedBy = value;

                if (inRoom != null)
                {
                    inRoom.Items.Remove(this);
                    inRoom = null;
                }

                if (inside != null)
                {
                    inside.Contents.Remove(this);
                    inside = null;
                }
            }
        }

        /// <summary>
        /// Gets or sets the contents.
        /// </summary>
        /// <value>The contents.</value>
        public ItemList Contents
        {
            get { return contents; }
            set
            {
                contents = value;

                foreach (Item item in contents)
                {
                    item.inside = this;
                }
            }
        }

        /// <summary>
        /// Gets the id.
        /// </summary>
        /// <value>The id.</value>
        [XmlIgnore]
        public uint Id
        {
            get { return index.Id; }
        }

        /// <summary>
        /// Gets or sets the index.
        /// </summary>
        /// <value>The index.</value>
        [XmlIgnore]
        public ItemIndex Index
        {
            get { return index; }
            set { index = value; }
        }

        /// <summary>
        /// Gets or sets the inside.
        /// </summary>
        /// <value>The inside.</value>
        [XmlIgnore]
        public Item Inside
        {
            get { return inside; }
            set
            {
                if (value != null)
                {
                    value.Contents.Add(this);
                }
                else if (inside != null)
                {
                    inside.Contents.Remove(this);
                }
                inside = value;

                if (inRoom != null)
                {
                    inRoom.Items.Remove(this);
                    inRoom = null;
                }

                if (carriedBy != null)
                {
                    carriedBy.Carrying.Remove(this);
                    carriedBy = null;
                }
            }
        }

        /// <summary>
        /// Gets or sets the room.
        /// </summary>
        /// <value>The room.</value>
        [XmlIgnore]
        public Room Room
        {
            get { return inRoom; }
            set
            {
                if (value != null)
                {
                    value.Items.Add(this);
                }
                else if (inRoom != null)
                {
                    inRoom.Items.Remove(this);
                }
                inRoom = value;

                if (carriedBy != null)
                {
                    carriedBy.Carrying.Remove(this);
                    carriedBy = null;
                }

                if (inside != null)
                {
                    inside.Contents.Remove(this);
                    inside = null;
                }
            }
        }

        /// <summary>
        /// Gets or sets the room descr.
        /// </summary>
        /// <value>The room descr.</value>
        public string RoomDescr
        {
            get { return roomDescr; }
            set { roomDescr = value; }
        }

        /// <summary>
        /// Gets the type.
        /// </summary>
        /// <value>The type.</value>
        [XmlIgnore]
        public ItemType Type
        {
            get { return index.Type; }
        }

        /// <summary>
        /// Gets or sets the wear loc.
        /// </summary>
        /// <value>The wear loc.</value>
        public WearLocation WearLoc
        {
            get { return wearLocation; }
            set { wearLocation = value; }
        }

        /// <summary>
        /// Gets or sets the index id.
        /// </summary>
        /// <value>The index id.</value>
        [XmlElement("Code")]
        public uint XmlIndex
        {
            get { return index.Id; }
            set { index = Lists.ItemIndexes[value]; }
        }

        /// <summary>
        /// Gets or sets the XML room.
        /// </summary>
        /// <value>The XML room.</value>
        [XmlElement("Room")]
        public uint XmlRoom
        {
            get { return inRoom.Id; }
            set { inRoom = Lists.Rooms[value]; }
        }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        /// <summary>
        /// Gets or sets the short descr.
        /// </summary>
        /// <value>The short descr.</value>
        public string ShortDescr
        {
            get { return shortDescr; }
            set { shortDescr = value; }
        }

        #endregion [rgn]

        #region [rgn] Methods (4)

        // [rgn] Public Methods (4)

        /// <summary>
        /// Attaches this instance to applicable lists.
        /// </summary>
        public void Attach()
        {
            Lists.Items.Add(this);
        }

        /// <summary>
        /// Releases this instance from applicable lists.
        /// </summary>
        public void Release()
        {
            Lists.Items.Remove(this);

            if (inRoom != null)
            {
                inRoom.Items.Remove(this);
                inRoom = null;
            }

            if (carriedBy != null)
            {
                carriedBy.Carrying.Remove(this);
                carriedBy = null;
            }

            if (inside != null)
            {
                inside.Contents.Remove(this);
                inside = null;
            }

            while (contents.Count > 0)
            {
                contents[0].Release();
            }
        }

        /// <summary>
        /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </returns>
        public override string ToString()
        {
            return shortDescr;
        }

        /// <summary>
        /// Get a string representation for a character.
        /// </summary>
        /// <param name="looker">The looker.</param>
        /// <returns></returns>
        public string ToString(Character looker)
        {
            return shortDescr;
        }

        #endregion [rgn]

        #region Scriptable Members

        /// <summary>
        /// Creates a script of proper type.
        /// </summary>
        /// <returns></returns>
        public Script CreateScript(ScriptCode code, String trigger)
        {
            return new ItemScript(code, trigger);
        }

        #endregion
    }
}