using System;
using System.Collections;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Volpe.Cafe.EspressoUI.LegacyControls
{
    /// <summary>
    /// Provides an object that is used to save messages which are displayed in the status label.
    /// </summary>
    public class Messages
    {

        #region /*** Nested Types ***/

        /// <summary>
        /// Provides an object to store messages.
        /// </summary>
        private struct Message
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="Message"/> class using the specified parameters.
            /// </summary>
            /// <param name="shortDescription">The short description (title or caption) of the message.</param>
            /// <param name="longDescription">The long description (details) of the message.</param>
            /// <param name="color">The color to associate with the message.</param>
            /// <param name="key">The key to associate with the message.</param>
            public Message(string shortDescription, string longDescription, Color color, object key)
            {
                this.ShortDescription = shortDescription;
                this.LongDescription = longDescription;
                this.Color = color;
                this.Key = key;
            }

            /// <summary>Specifies the short description (title or caption) of the message.</summary>
            public string ShortDescription;
            /// <summary>Specifies the long description (details) of the message.</summary>
            public string LongDescription;
            /// <summary>Specifies the color associated with this <see cref="Message"/> instance.</summary>
            public Color Color;
            /// <summary>Specifies the key associated with this <see cref="Message"/> instance.</summary>
            public object Key;
        }

        #endregion


        #region /*** Events ***/

        /// <summary>Occurs whenever a message is added or removed from the internal message list.</summary>
        public event EventHandler MessagesChanged;

        #endregion


        #region /*** Constructors ***/

        /// <summary>
        /// Initializes a new instance of the Messages class.
        /// </summary>
        public Messages()
        {
            this._list = new ArrayList();
        }

        #endregion


        #region /*** Methods ***/

        /// <summary>
        /// Adds a new message with the specified parameters to the internal list.
        /// </summary>
        /// <param name="shortDescription">The short description (title or caption) of the message.</param>
        /// <param name="longDescription">The long description (details) of the message.</param>
        /// <param name="color">The color to associate with the message.</param>
        /// <param name="key">The key to associate with the message.</param>
        public void AddMessage(string shortDescription, string longDescription, Color color, object key)
        {
            // first remove any existing messages with this key
            this.RemoveMessage(key);
            // then add the new message with this key
            this._list.Add(new Message(shortDescription, longDescription, color, key));
            // raise the MessagesChanged event
            this.OnMessagesChanged(EventArgs.Empty);
        }
        /// <summary>
        /// Removes all messages with the specified key.
        /// </summary>
        /// <param name="key">The key of the message to remove.</param>
        public void RemoveMessage(object key)
        {
            int index = this.FindMessage(key);
            while (index != -1)
            {
                this.RemoveMessage(index);
                index = this.FindMessage(key);
            }
        }
        /// <summary>
        /// Removes the message from the internal list at the specified index.
        /// </summary>
        /// <param name="index">The index at which to remove the message.</param>
        public void RemoveMessage(int index)
        {
            if (index != -1)
            {   // remove the element
                this._list.RemoveAt(index);
                // raise the MessagesChanged event
                this.OnMessagesChanged(EventArgs.Empty);
            }
        }
        /// <summary>
        /// Removes all messages from the internal messages list.
        /// </summary>
        public void ClearMessages()
        {
            // clear the list
            this._list.Clear();
            // raise the MessagesChanged event
            this.OnMessagesChanged(EventArgs.Empty);
        }
        /// <summary>
        /// Searches for and returns the index of the message with the specified key.
        /// </summary>
        /// <param name="key">The key of the message to searh for.</param>
        /// <returns>The index of the message with the specified key, or -1 if the key is not found.</returns>
        public int FindMessage(object key)
        {
            for (int i = 0; i < this._list.Count; i++)
            {
                if (((Message)this._list[i]).Key == key)
                {
                    return i;
                }
            }
            return -1;
        }


        /// <summary>
        /// Converts this <see cref="Messages"/> instance to the equivalent string representation, using short message descriptions.
        /// </summary>
        /// <returns>A string that represents the current <see cref="Messages"/> instance.</returns>
        public override string ToString()
        {
            StringBuilder sb = new System.Text.StringBuilder();
            for (int i = 0; i < this._list.Count; i++)
            {
                Message msg = (Message)this._list[i];
                sb.Append(msg.ShortDescription);
                sb.Append("\n");
            }
            return sb.ToString();
        }
        /// <summary>
        /// Converts this <see cref="Messages"/> instance to the equivalent string representation, using short and long message descriptions.
        /// </summary>
        /// <returns>A string that represents the current <see cref="Messages"/> instance.</returns>
        public string ToStringDetailed()
        {
            StringBuilder sb = new System.Text.StringBuilder();
            for (int i = 0; i < this._list.Count; i++)
            {
                Message msg = (Message)this._list[i];
                sb.Append(msg.ShortDescription);
                if (msg.LongDescription != null && msg.LongDescription != string.Empty)
                {
                    sb.Append("\n\n");
                    sb.Append(msg.LongDescription);
                    sb.Append("\n");
                }
                sb.Append("\n");
            }
            return sb.ToString();
        }


        /// <summary>
        /// Raises a <see cref="MessagesChanged"/> event.
        /// </summary>
        /// <param name="e">The System.EventArgs object that contains the event data.</param>
        protected void OnMessagesChanged(EventArgs e)
        {
            this.MessagesChanged?.Invoke(this, e);
        }

        #endregion


        #region /*** Properties ***/

        /// <summary>Gets whether this <see cref="Messages"/> instance contains any actual messages.</summary>
        public bool HasMessages { get { return (this._list.Count > 0); } }

        #endregion


        #region /*** Variables ***/

        /// <summary>Stores an internal list of messages.</summary>
        ArrayList _list;

        #endregion

    }
}
