/
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;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using Arthea.Abilities.Skills;
using Arthea.Clans;
using Arthea.Classes;
using Arthea.Commands;
using Arthea.Commands.Admin;
using Arthea.Connections.Colors;
using Arthea.Continents.Areas;
using Arthea.Continents.Areas.Characters;
using Arthea.Creation;
using Arthea.Creation.Attributes;
using Arthea.Environment;
using Arthea.Interfaces;

namespace Arthea.Connections.Players
{
    /// <summary>
    /// Implements a player
    /// </summary>
    public class Player : Character
    {
        #region [rgn] Fields (13)

        private Clan clan;
        [EditIgnore] private Color[] colors = CustomColor.CreateColorArray();
        private PlayerConfig config = new PlayerConfig(PlayerConfig.Color);
        [EditIgnore] private Connection connection;
        private int experience;
        private SkillValues learned = new SkillValues();
        private DateTime login = DateTime.Now;
        private string password;
        private TimeSpan played = new TimeSpan();
        private PowerList powers = new PowerList();
        private string prompt;
        private PlayerStats stats = new PlayerStats();
        private string title;

        #endregion [rgn]

        #region [rgn] Constructors (2)

        /// <summary>
        /// Initializes a new instance of the <see cref="Player"/> class.
        /// </summary>
        /// <param name="conn">The conn.</param>
        /// <param name="name">The name.</param>
        public Player(Connection conn, String name) : base(0, name)
        {
            connection = conn;
            initialize();
        }

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

        #endregion [rgn]

        #region [rgn] Properties (22)

        /// <summary>
        /// Gets the area.
        /// </summary>
        /// <value>The area.</value>
        public override Area Area
        {
            get { return Room.Area; }
        }

        /// <summary>
        /// Gets or sets the clan.
        /// </summary>
        /// <value>The clan.</value>
        [XmlIgnore]
        public Clan Clan
        {
            get { return clan; }
            set
            {
                if (value == null && clan != null)
                {
                    clan.Members.Remove(this);
                }
                clan = value;
                if (value != null)
                {
                    clan.Members.Add(this);
                }
            }
        }

        /// <summary>
        /// Gets or sets the class.
        /// </summary>
        /// <value>The class.</value>
        [XmlIgnore]
        public Class Class
        {
            get { return @class; }
            set { @class = value; }
        }

        /// <summary>
        /// Gets or sets the colors.
        /// </summary>
        /// <value>The colors.</value>
        [XmlIgnore]
        public Color[] Colors
        {
            get { return colors; }
            set { colors = value; }
        }

        /// <summary>
        /// Gets or sets the config.
        /// </summary>
        /// <value>The config.</value>
        public PlayerConfig Config
        {
            get { return config; }
            set { config = value; }
        }

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

        /// <summary>
        /// Gets or sets the experience.
        /// </summary>
        /// <value>The experience.</value>
        public int Experience
        {
            get { return experience; }
            set { experience = value; }
        }

        /// <summary>
        /// Gets or sets learned skills.
        /// </summary>
        /// <value>The list of learned skills.</value>
        public SkillValues Learned
        {
            get { return learned; }
            set { learned = value; }
        }

        /// <summary>
        /// Gets or sets the login.
        /// </summary>
        /// <value>The login.</value>
        public DateTime Login
        {
            get { return login; }
            set { login = value; }
        }

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

        /// <summary>
        /// Gets or sets the time played.
        /// </summary>
        /// <value>The time played.</value>
        public TimeSpan Played
        {
            get { return played; }
            set { played = value; }
        }

        /// <summary>
        /// Gets or sets the powers.
        /// </summary>
        /// <value>The powers.</value>
        public PowerList Powers
        {
            get { return powers; }
            set { powers = value; }
        }

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

        /// <summary>
        /// Gets the room descr.
        /// </summary>
        /// <value>The room descr.</value>
        [XmlIgnore]
        public override string RoomDescr
        {
            get
            {
                return string.Format("{0}{1} is here.",
                                     Config.Has(PlayerConfig.AFK) ? "(AFK) " : "", Name);
            }
        }

        /// <summary>
        /// Gets or sets the screen height
        /// Will not set if NAWS has been detected.
        /// </summary>
        /// <value>the screen height</value>
        [XmlElement("ScreenHeight", typeof (int))]
        public int ScreenHeight
        {
            get { return connection.ScreenHeight; }
            set
            {
                if (connection != null && !connection.Flags.Has(ConnectionFlags.NAWS))
                    connection.ScreenHeight = value;
            }
        }

        /// <summary>
        /// Gets ot sets the screen width
        /// Will not set if NAWS has been detected.
        /// </summary>
        /// <value>the screen width</value>
        [XmlElement("ScreenWidth", typeof (int))]
        public int ScreenWidth
        {
            get { return connection.ScreenWidth; }
            set
            {
                if (connection != null && !connection.Flags.Has(ConnectionFlags.NAWS))
                    connection.ScreenWidth = value;
            }
        }

        /// <summary>
        /// Gets the short descr.
        /// </summary>
        /// <value>The short descr.</value>
        [XmlIgnore]
        public override string ShortDescr
        {
            get { return Name; }
        }

        /// <summary>
        /// Gets or sets the stats.
        /// </summary>
        /// <value>The stats.</value>
        public PlayerStats Stats
        {
            get { return stats; }
            set { stats = value; }
        }

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

        /// <summary>
        /// Gets or sets the clan name
        /// </summary>
        /// <value>The clan name.</value>
        [XmlElement("Clan")]
        public string XmlClan
        {
            get { return clan == null ? "" : clan.Name; }
            set { clan = Lists.Clans.FindName(value); }
        }

        /// <summary>
        /// Gets or sets the class as a string.
        /// </summary>
        /// <value>The class as a string.</value>
        [XmlElement("Class")]
        public string XmlClass
        {
            get { return (@class != null) ? @class.ToString() : ""; }
            set { @class = Lists.Classes.FindName(value); }
        }

        /// <summary>
        /// Gets or sets the XML colors.
        /// </summary>
        /// <value>The XML colors.</value>
        [XmlElement("CustomColors")]
        public string XmlColors
        {
            get
            {
                StringBuilder buf = new StringBuilder();

                for (int i = 0; i < colors.Length; i++)
                {
                    if (i != 0)
                        buf.Append(",");
                    buf.Append(colors[i].ToString(0));
                }

                return buf.ToString();
            }
            set
            {
                string[] values = value.Split(',');

                for (int i = 0; i < values.Length; i++)
                {
                    colors[i] = Color.Parse(values[i]);
                }
            }
        }

        #endregion [rgn]

        #region [rgn] Methods (9)

        // [rgn] Public Methods (8)

        /// <summary>
        /// Attaches this instance to applicable lists.
        /// </summary>
        public override void Attach()
        {
            base.Attach();

            Lists.Players.Add(this);
        }

        /// <summary>
        /// Determines whether this instance [can gain level].
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if this instance [can gain level]; otherwise, <c>false</c>.
        /// </returns>
        public bool CanGainLevel()
        {
            return false;
        }

        /// <summary>
        /// Displays a prompt.
        /// </summary>
        public void DisplayPrompt()
        {
            if (Connection.Composing != null)
            {
                Write("Enter a line of text (/h for help):");
            }
            else if (string.IsNullOrEmpty(prompt))
            {
                if (Connection.Editing == null)
                    Write("> ");
                else
                    Write("{0}> ", Connection.Editing);
            }

            else if (!prompt.Contains("%"))
            {
                Write("{0} ", prompt);
            }
            else
            {
                StringBuilder buf = new StringBuilder();

                for (IEnumerator<char> ch = prompt.GetEnumerator(); ch.MoveNext();)
                {
                    if (ch.Current != '%')
                    {
                        buf.Append(ch.Current);
                        continue;
                    }

                    if (!ch.MoveNext())
                        break;

                    switch (ch.Current)
                    {
                        case 'E':
                            if (Connection.Editing != null)
                                buf.Append(Connection.Editing);
                            break;
                        case 'R':
                            buf.Append(Room.ToString(this));
                            break;
                        case 'A':
                            buf.Append(Room.Area);
                            break;
                        default:
                            Log.Bug("DisplayPrompt: Bad format %{0}.", ch);
                            break;
                    }
                }
                buf.Append(" ");
                Write(buf.ToString());
            }
            Connection.SentPrompt = true;
        }

        /// <summary>
        /// Draws a line.
        /// </summary>
        public void DrawLine()
        {
            StringBuilder buf = new StringBuilder();

            for (int i = 0; i < 80; i++)
            {
                buf.Append("-");
            }

            WriteLine(buf.ToString());
        }

        /// <summary>
        /// Loads the specified name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static Player Load(string name)
        {
            return Persistance.Load<Player>(Paths.PlayerDir + name);
        }

        /// <summary>
        /// Removes character from lists
        /// </summary>
        public override void Release()
        {
            base.Release();

            Lists.Players.Remove(this);
        }

        /// <summary>
        /// Saves this instance.
        /// </summary>
        public void Save()
        {
            Persistance.Save(Paths.PlayerDir + Name, this);
        }

        /// <summary>
        /// A string representation of a player.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return Name;
        }

        // [rgn] Private Methods (1)

        /// <summary>
        /// Inits the player.
        /// </summary>
        private void initialize()
        {
            RoomDescrSpecified = false;
            ShortDescrSpecified = false;
            XmlIndexSpecified = false;
        }

        #endregion [rgn]

        private Class @class;

        #region Write Methods

        /// <summary>
        /// Writes the specified text.
        /// </summary>
        /// <param name="text">The text.</param>
        public override void Write(string text)
        {
            connection.Write(text);
        }

        /// <summary>
        /// Writes the specified text.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="args">The args.</param>
        public override void Write(string text, params object[] args)
        {
            connection.Write(text, args);
        }

        /// <summary>
        /// Writes a line.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="args">The args.</param>
        public override void WriteLine(string text, params object[] args)
        {
            connection.WriteLine(text, args);
        }

        /// <summary>
        /// Writes an object.
        /// </summary>
        /// <param name="obj">The obj.</param>
        public void WriteLine(object obj)
        {
            connection.WriteLine(obj.ToString());
        }

        /// <summary>
        /// Writes a line.
        /// </summary>
        public override void WriteLine()
        {
            connection.WriteLine();
        }

        #endregion
    }

    /// <summary>
    /// Implements a power list
    /// </summary>
    public class PowerList : List<string>, CustomEditType
    {
        #region [rgn] Properties (2)

        /// <summary>
        /// Gets the <see cref="System.Boolean"/> with the specified power.
        /// </summary>
        /// <value>true if power is contained</value>
        public bool this[Powers power]
        {
            get { return Contains(power.ToString().ToLower()); }
        }

        /// <summary>
        /// Gets the <see cref="System.Boolean"/> with the specified CMD.
        /// </summary>
        /// <value>true if cmd is contained</value>
        public bool this[Command cmd]
        {
            get { return Contains(cmd.Name); }
        }

        #endregion [rgn]

        #region [rgn] Methods (6)

        // [rgn] Public Methods (6)

        /// <summary>
        /// Sets the value of this instance.
        /// </summary>
        /// <param name="player">The player.</param>
        /// <param name="editer">Information from the editer.</param>
        /// <param name="argument">The argument.</param>
        public void CustomEdit(Player player, OlcField editer, String argument)
        {
            try
            {
                Powers power = (Powers) Enum.Parse(typeof (Powers), argument, true);
                Add(power);
                player.WriteLine("{0}: {1} set.", editer.Name, power);
            }
            catch
            {
                Command cmd = Lists.Commands.FindName(argument);

                if (cmd == null || cmd.Level != Levels.Admin)
                {
                    player.WriteLine("That is not an admin command.");

                    GrantCommand.ValidPowers(player);

                    return;
                }

                Add(cmd);
                player.WriteLine("{0}: {1} set.", editer.Name, cmd);
            }
        }

        /// <summary>
        /// Adds the specified power.
        /// </summary>
        /// <param name="power">The power.</param>
        public void Add(Powers power)
        {
            Add(power.ToString().ToLower());
        }

        /// <summary>
        /// Adds the specified command.
        /// </summary>
        /// <param name="cmd">The command.</param>
        public void Add(Command cmd)
        {
            Add(cmd.Name.ToLower());
        }

        /// <summary>
        /// Removes the specified power.
        /// </summary>
        /// <param name="power">The power.</param>
        /// <returns>true if sucessful</returns>
        public bool Remove(Powers power)
        {
            return Remove(power.ToString().ToLower());
        }

        /// <summary>
        /// Removes the specified command.
        /// </summary>
        /// <param name="cmd">The command.</param>
        /// <returns>true if succesful.</returns>
        public bool Remove(Command cmd)
        {
            return Remove(cmd.Name.ToLower());
        }

        /// <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()
        {
            StringBuilder buf = new StringBuilder();

            foreach (string str in this)
            {
                buf.Append(str);
                buf.Append(",");
            }

            if (buf.Length > 0)
                buf.Remove(buf.Length - 1, 1);

            return buf.ToString();
        }

        #endregion [rgn]
    }
}