using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

using VRH.Log4Pro.MultiLanguageManager;
using Vrh.XmlProcessing;

namespace Vrh.iScheduler
{
    /// <summary>
    /// Egy kezelő gomb leírására szolgáló osztály
    /// </summary>
    public class ButtonElement : XmlLinqBase
    {
        #region Constants
        private const string ERR_ROWCOL = "The value of the attribute \"{0}\" must be less than 11 and more than 0!";
        #endregion Constants

        #region Built'in classes

        #region ElementNames class
        /// <summary>
        /// Az XML fájlban ilyen elem nevek találhatóak egy "Button" elemben.
        /// </summary>
        private new class ElementNames : XmlLinqBase.ElementNames
        {
            /// <summary>
            /// 'url' elem név.
            /// </summary>
            public const string URL = "url";
        }
        #endregion ElementNames class

        #region AttributeNames static class
        /// <summary>
        /// Az XML fájlban ilyen attribútum nevek találhatóak egy 'Button' elemben.
        /// </summary>
        private static class AttributeNames
        {
            /// <summary>
            /// 'Col' attribútum név.
            /// </summary>
            public const string COL = "Col";

            /// <summary>
            /// 'Dialog' attribútum név.
            /// </summary>
            public const string DIALOG = "Dialog";

            /// <summary>
            /// 'DialogSize' attribútum név.
            /// </summary>
            public const string DIALOGSIZE = "DialogSize";

            /// <summary>
            /// 'HSpan' attribútum név.
            /// </summary>
            public const string HSPAN = "HSpan";

            /// <summary>
            /// 'Name' attribútum név.
            /// </summary>
            public const string NAME = "Name";

            /// <summary>
            /// 'Row' attribútum név.
            /// </summary>
            public const string ROW = "Row";

            /// <summary>
            /// 'Style' attribútum név.
            /// </summary>
            public const string STYLE = "Style";

            /// <summary>
            /// 'Type' attribútum név.
            /// </summary>
            public const string TYPE = "Type";

			/// <summary>
			/// 'Label' attribútum név.
			/// </summary>
			public const string LABEL = "Label";

			/// <summary>
			/// 'WSpan' attribútum név.
			/// </summary>
			public const string WSPAN = "WSpan";
        }
        #endregion AttributeNames static class

        #region SysButtonNames public static class
        /// <summary>
        /// sys típusú kezelő gombok lehetséges nevei.
        /// </summary>
        public static class SysButtonNames
        {
            /// <summary>
            /// Konzisztencia ellenőrzése rendszer gomb neve.
            /// </summary>
            public const string ConsistencyCheck = "ConsistencyCheck";

            /// <summary>
            /// A listanézetre való váltás gombjának a neve.
            /// </summary>
            public const string GoToListView = "GoToListView";

            /// <summary>
            /// A naptár nézetre való váltás gombjának a neve.
            /// </summary>
            public const string GoToMonthView = "GoToMonthView";

            /// <summary>
            /// Az új ütemezés létrehozás gombjának neve.
            /// </summary>
            public const string NewSchedule = "NewSchedule";

            /// <summary>
            /// Az ütemezendő objektum kezelő felületét elindító gomb neve.
            /// </summary>
            public const string ObjectManager = "ObjectManager";    //WA20170626-#8390
        }
        #endregion SysButtonNames public static class

        #endregion Built'in classes

        #region Properties

        /// <summary>
        /// A gomb megnevezése a HTML-ben a name attribútum értéke.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// A gomb típusa. "sys", ha beépített, "url", ha nem.
        /// </summary>
        public ButtonTypes ButtonType { get; set; }

        /// <summary>
        /// A megjelenítendő szöveg. 
        /// Kapcsoló gomb esetén a bekapcsolt állapot szövege.
        /// Ide már a lefordított szöveg kerül.
        /// </summary>
        public string ButtonLabel { get; set; }

        /// <summary>
        /// Kapcsoló gomb esetén a kikapcsolt állapot szövege.
        /// Ide már a lefordított szöveg kerül.
        /// </summary>.-
        public string ButtonlabelOff { get; set; }

        /// <summary>
        /// A gomb mátrixban elfoglalt cella sora.
        /// </summary>
        public int Row { get; set; }

        /// <summary>
        /// A gomb mátrixban elfoglalt cella oszlopa.
        /// </summary>
        public int Col { get; set; }

        /// <summary>
        /// Magasságban (Heigth, HSpan) egyesítendő cellák száma. Alapértelmezése 1.
        /// </summary>
        public int RowSpan { get; set; }

        /// <summary>
        /// Szélességben (Width, WSpan) egyesítendő cellák száma. Alapértelmezése 1.
        /// </summary>
        public int ColSpan { get; set; }

        /// <summary>
        /// HTML stílusokban alkalmazható stílus.
        /// </summary>
        public string Style { get; set; }

        /// <summary>
        /// Az elindítandó url ablakban jelenjen-e meg.
        /// Ha a gomb neve "NewSchedule", akkor mindig true!
        /// </summary>
        public bool IsDialog { get; set; }

        /// <summary>
        /// Ha az elindítandó url ablakban jelenik meg, akkor az milyen széles legyen.
        /// Alapértelmezett értéke 600px.
        /// </summary>
        public string DialogSize { get; set; }

        /// <summary>
        /// url típusú gombok esetében a meghívandó akció leírója.
        /// </summary>
        public UrlElement Url { get; set; }

        #endregion Properties

        #region Constructors
        /// <summary>
        /// Példányosítás egy 'Button' XElement alapján.
        /// </summary>
        /// <param name="xelement">A 'Button' elem XElement objektuma.</param>
        /// <param name="lcid">A környezetben érvényes nyelvi kód.</param>
        /// A gomboknál lévő szókód lesz hozzáfűzve. 
        /// Így alkotják a gomb megjelenő nevének szókódját.
        /// </param>
        //public ButtonElement(XElement xelement, string lcid, string wordCodePrefix)
		public ButtonElement(XElement xelement, string lcid)
		{
            if (xelement != null)
            {
                this.Name = GetValue(AttributeNames.NAME, xelement, "", true, true);
                
                #region ButtonType beolvasása és ellenőrzése
                string type = GetValue(AttributeNames.TYPE, xelement, "", true, true);
                if (Enum.TryParse<ButtonTypes>(type, true, out ButtonTypes btype))
                {
                    this.ButtonType = btype;
                }
                else
                {
                    throw new ApplicationException(string.Format(
                        "The possible values for \"Button.Type\" attribute \"{0}\"! Button.Name = \"{1}\"",
                        string.Join(", ", Enum.GetNames(typeof(ButtonTypes))), this.Name                        
                    ));
                }

                #endregion ButtonType beolvasása és ellenőrzése

                this.Row = GetValue(AttributeNames.ROW, xelement, 1, true, true);
                this.Col = GetValue(AttributeNames.COL, xelement, 1, true, true);
                this.RowSpan = GetValue(AttributeNames.HSPAN, xelement, 1);
                this.ColSpan = GetValue(AttributeNames.WSPAN, xelement, 1);
                this.Style = GetValue(AttributeNames.STYLE, xelement, "color:white;background-color:#45b845;");
                this.IsDialog = GetValue(AttributeNames.DIALOG, xelement, false);
                string ds = GetValue(AttributeNames.DIALOGSIZE, xelement, "");
                this.DialogSize = string.IsNullOrWhiteSpace(ds) ? "600px" : ds;

                #region Row, Col, RowSpan, ColSpan ellenőrzése
                if (this.Row < 1 || this.Row > 10)
                {
                    throw new ApplicationException(string.Format(ERR_ROWCOL,"Button.Row"));
                }
                if (this.Col < 1 || this.Col > 10)
                {
                    throw new ApplicationException(string.Format(ERR_ROWCOL, "Button.Col"));
                }
                if (this.RowSpan < 1 || this.RowSpan > 10)
                {
                    throw new ApplicationException(string.Format(ERR_ROWCOL, "Button.HSpan"));
                }

                if (this.ColSpan < 1 || this.ColSpan > 10)
                {
                    throw new ApplicationException(string.Format(ERR_ROWCOL, "Button.WSpan"));
                }
				#endregion Row, Col, RowSpan, ColSpan ellenőrzése

				#region Display 
				if (this.ButtonType == ButtonTypes.Sys)
				{
					switch (this.Name)
					{
						case SysButtonNames.ConsistencyCheck:
							this.ButtonLabel = MultiLanguageManager.GetTranslation(typeof(SchedulerWordCodes.iScheduler.Manager.Button.ConsistencyCheckOn), lcid);
							this.ButtonlabelOff = MultiLanguageManager.GetTranslation(typeof(SchedulerWordCodes.iScheduler.Manager.Button.ConsistencyCheckOff), lcid);
							break;
						case SysButtonNames.GoToListView: this.ButtonLabel = MultiLanguageManager.GetTranslation(typeof(SchedulerWordCodes.iScheduler.Manager.Button.GoToListView), lcid); break;
						case SysButtonNames.GoToMonthView: this.ButtonLabel = MultiLanguageManager.GetTranslation(typeof(SchedulerWordCodes.iScheduler.Manager.Button.GoToMonthView), lcid); break;
						case SysButtonNames.NewSchedule: this.ButtonLabel = MultiLanguageManager.GetTranslation(typeof(SchedulerWordCodes.iScheduler.Manager.Button.NewSchedule), lcid); break;
						case SysButtonNames.ObjectManager: this.ButtonLabel = MultiLanguageManager.GetTranslation(typeof(SchedulerWordCodes.iScheduler.Manager.Button.ObjectManager), lcid); break;
					}
				}
				else 
				{ 
					this.ButtonLabel = GetValue(AttributeNames.LABEL, xelement, this.Name);
					if (string.IsNullOrEmpty(this.ButtonLabel)) { this.ButtonLabel = this.Name; }
				}
				#endregion Display

				#region Gomb nevének ellenőrzése, url típus beolvasása
				if (this.ButtonType == ButtonTypes.Sys)
                {
                    switch(this.Name)
                    {
                        case SysButtonNames.ConsistencyCheck:
                        case SysButtonNames.NewSchedule:
                        case SysButtonNames.GoToListView:
                        case SysButtonNames.GoToMonthView:
                        case SysButtonNames.ObjectManager:  //WA20170629-#8390
                            break;
                        default:
                            throw new ApplicationException(string.Format(
                                "The possible values for 'Button.Name' attribute if the Type='sys' " +
                                "{0}, {1}, {2}, {3}, {4} ! Name = {5}",
                                SysButtonNames.ConsistencyCheck, SysButtonNames.ObjectManager,
                                SysButtonNames.GoToListView, SysButtonNames.GoToMonthView,
                                SysButtonNames.NewSchedule, this.Name));
                    }
                }
                else
                {   //nem sys típusú gombok, azok viszont nem vehetik fel a sys gombok nevét!
                    switch (this.Name)
                    {
                        case SysButtonNames.ConsistencyCheck:
                        case SysButtonNames.NewSchedule:
                        case SysButtonNames.GoToListView:
                        case SysButtonNames.GoToMonthView:
                        case SysButtonNames.ObjectManager:  //WA20170629-#8390
                            throw new ApplicationException(string.Format(
                                "If the Type='url', then the names can not be the following: " +
                                "{0}, {1}, {2}, {3}, {4} ! Name = {5}",
                                SysButtonNames.ConsistencyCheck, SysButtonNames.ObjectManager,
                                SysButtonNames.GoToListView, SysButtonNames.GoToMonthView,
                                SysButtonNames.NewSchedule, this.Name));
                        default:
                            break;
                    }

                    XElement urlXE = xelement.Element(ElementNames.URL);
                    if (urlXE == null)
                    {
                        throw new ApplicationException(string.Format(XmlLinqBase.Messages.ERR_MISSINGELEMENT, ElementNames.URL));
                    }
                    this.Url = new UrlElement(urlXE);
                    if (this.Url != null && this.Url.UrlParameters != null)
                    {
                        if (this.Url.UrlParameters.Any(x => x.PassTo.ToLower() == UrlElement.ParameterTypes.dict))
                        {
                            throw new ApplicationException("The Button.Url.inputparameter.PassTo=\"dict\" attribute are not allowed in this context!");
                        }
                    }
                }
                #endregion Gomb nevének ellenőrzése, url típus beolvasása
            }
        }
        #endregion Constructors
    }
}
