using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Mvc;

using VRH.Log4Pro.MultiLanguageManager;
using Vrh.Web.Common.Lib;

using Vrh.iScheduler;

namespace Vrh.Web.iScheduler
{
    /// <summary>
    /// A Manager és Editor cshtml-ek számára szükséges model.
    /// </summary>
    public class SchedulerModel : CommonModel
    {
        #region Properties    
        /// <summary>
        /// A már kielemzett iScheduler XML.
        /// </summary>
        public SchedulerXmlParser Scheduler { get; set; }

        /// <summary>
        /// A Schedules tábla egyedi azonosítója, mely egy ütemezést azonosít.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Manager.Label.Id))]
        public int Id { get; set; } = 0;

        /// <summary>
        /// Kiválasztot objektum azonosítója.
        /// </summary>
        public string ObjectIdValue { get; set; }

        /// <summary>
        /// Kiválasztot objektum megnevezése.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Manager.Label.ObjectId))]
        [LocaleRequired]
        public string ObjectIdText { get; set; }

        /// <summary>
        /// Kiválasztot művelet azonosítója.
        /// </summary>
        public string OperationIdValue { get; set; }

        /// <summary>
        /// Kiválasztot művelet megnevezése.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Manager.Label.OperationId))]
        [LocaleRequired]
        public string OperationIdText { get; set; }

        /// <summary>
        /// Az ütemezés időpontja, amikor a műveletet végre kell hajtani.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Manager.Label.OperationTime))]
        [LocaleRequired]
        public DateTime OperationTime { get; set; }

        /// <summary>
        /// Az objektum típusa. ReadOnly
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Manager.Label.ObjectTpye))]
        [LocaleRequired]
        public string ObjectType { get; set; }

        /// <summary>
        /// Az ütemezés időpontja, amikor a műveletet végre kell hajtani.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Manager.Label.ObjectGroupId))]
        [LocaleRequired]
        public string ObjectGroupId { get; set; }

        /// <summary>
        /// Az ütemezés állapota
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Manager.Label.State))]
        public ScheduleStates State { get; set; }

        /// <summary>
        /// Az állapot megadott nyelvre fordítva.
        /// </summary>
        public string StateTranslate { get; set; }

        /// <summary>
        /// Állapotok szűréséhez a választó lista.
        /// </summary>
        public List<SelectListItem> StateFilterList { get; set; }

        /// <summary>
        /// Ha már létezik az ütemezéshez visszatérő üzenet, akkor annak megjelenítése.
        /// Értékét az Editor GET részében kell beállítani.
        /// </summary>
        public bool IsExistReturnMessage { get; set; } = false;

        /// <summary>
        /// Az ütemezésben rögzített visszatérő üzenet, akkor annak megjelenítése.
        /// </summary>
        public string ReturnMessage { get; set; } = "";

        /// <summary>
        /// Ha az ütemezés egy sorozat tagja, akkor annak azonosítója.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Manager.Label.SeriesId))]
        public int? SeriesId { get; set; } = null;

        /// <summary>
        /// Ütemezése típusa.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.ScheduleType))]
        public string ScheduleType { get; set; }

        /// <summary>
        /// Ha ütemezés típusának átváltása történik, azt fel kell ismerni valahogy.
        /// Ez szolgál arra, hogy a POST-ban észre lehessen venni, ha megváltoztatták az ütemezés típusát.
        /// </summary>
        public string PreviousScheduleType { get; set; }

        #region Standard properties for the series 

        /// <summary>
        /// Hetek vagy hónapok száma, minimum 1. 
        /// </summary>
        public int NumberOf { get; set; } = 1;

        /// <summary>
        /// Ha az ütemezés egy sorozat tagja, akkor annak típusa.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.SeriesName))]
        public string SeriesName { get; set; } = null;

        /// <summary>
        /// Ha az ütemezés egy sorozat tagja, akkor annak színe.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.SeriesColor))]
        public string SeriesColor { get; set; } = null;

        #endregion Standard properties for the series 

        #region Days of the week
        /// <summary>
        /// A kiválasztott napokat tartalmazó tömb.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Days))]
        public int[] SelectedWeekDays { get; set; } = new[] { 1, 2, 3, 4, 5 };

        /// <summary>
        /// Igaz, ha hétfő is kiválasztott.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Monday))]
        public bool IsMonday { get; set; } = true;

        /// <summary>
        /// Igaz, ha Kedd is kiválasztott.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Tuesday))]
        public bool IsTuesday { get; set; } = true;

        /// <summary>
        /// Igaz, ha Szerda is kiválasztott.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Wednesday))]
        public bool IsWednesday { get; set; } = true;

        /// <summary>
        /// Igaz, ha Csütörtök is kiválasztott.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Thursday))]
        public bool IsThursday { get; set; } = true;

        /// <summary>
        /// Igaz, ha Péntek is kiválasztott.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Friday))]
        public bool IsFriday { get; set; } = true;

        /// <summary>
        /// Igaz, ha Szombat is kiválasztott.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Saturday))]
        public bool IsSaturday { get; set; } = false;

        /// <summary>
        /// Igaz, ha Vasárnap is kiválasztott.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Sunday))]
        public bool IsSunday { get; set; } = false;

        #endregion Days of the week

        /// <summary>
        /// Annak a jelzése, hogy az Editor mentése után legyen-e végrehajtás.
        /// </summary>
        [DisplayNameWithTrueWordCodes(typeof(SchedulerWordCodes.iScheduler.Editor.Label.ScheduleExecute))]
        public bool IsScheduleExecute { get; set; } = false;

        /// <summary>
        /// A dátumformátum megőrzése céljából.
        /// </summary>
        public string DateTimeFormat { get; set; } = Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern;

        /// <summary>
        /// A kapcsolati sztringet is meg kell őrizni.
        /// </summary>
        public string ConnectionString { get; set; }

        /// <summary>
        /// Az ObjectId lekérdezéséhez szükséges URL. 
        /// </summary>
        public string ObjectIdUrl { get; set; }

        /// <summary>
        /// Az OperationId lekérdezéséhez szükséges URL.
        /// </summary>
        public string OperationIdUrl { get; set; }

        /// <summary>
        /// Az ObjectEditor indításához szükséges URL.
        /// </summary>
        public string ObjectEditorUrl { get; set; }

        /// <summary>
        /// A CheckObjects indításához szükséges URL.
        /// </summary>
        public string CheckObjectsUrl { get; set; }

        /// <summary>
        /// Annak jelzése, hogy milyen nézetből hívták az editor.
        /// Null érték azt jelenti, hogy nem a list és nem is a calendar nézetből hívták.
        /// </summary>
        public string CallingViewMode { get; set; } = null;

        /// <summary>
        /// Az éppen érvényes nézet.
        /// </summary>
        public string CurrentViewMode { get; set; } = DisplayMode.List.ToString();

        /// <summary>
        /// Konzisztencia ellenőrzés alatt a táblázat fölé kiírandó üzenet.
        /// </summary>
        public string ConsistencyHeader { get; set; } = "";

        /// <summary>
        /// A konzisztencia ellenőrzés gombjának stílusa, amely a bekapcsolt állapotot jelenti.
        /// </summary>
        public string ConsistencyStyle { get; set; } = "";

        /// <summary>
        /// Konzisztencia ellenőrzéshez használt akció iScheduler controller-be hívó Url. 
        /// </summary>
        public string ConsistencyUrl { get; set; } = "";

        /// <summary>
        /// Meg kell őrizni a POST számára, mert ott fog kelleni.
        /// </summary>
        public string XmlParserConnectionString { get; set; }

        #endregion Properties    

        #region Constructor
        /// <summary>
        /// A view-hoz használt model konstruktora.
        /// </summary>
        public SchedulerModel()
        {
            this.SelectedWeekDays = new[] { 1, 2, 3, 4, 5 };
        }

        /// <summary>
        /// A view-hoz használt model konstruktora, de itt meg kell adni a már feldolgozott xml struktúrát.
        /// </summary>
        /// <param name="isxp">A már feldolgozott xml struktúra.</param>
        /// <param name="displayMode">Aktuális megjelenítési mód.</param>
        public SchedulerModel(SchedulerXmlParser isxp, string displayMode = null) : this()
        {
            this.Scheduler = isxp ?? throw new ArgumentNullException("_scheduler");
            this.CurrentViewMode = isxp.Manager.DefaultDisplayMode.ToString();

            #region Értékek a post részére (hidden)

            this.CallingViewMode = string.IsNullOrWhiteSpace(displayMode) ? null : displayMode;
            this.ConnectionString = isxp.ConnectionString;
            this.XmlParserConnectionString = isxp.XmlParserConnectionString;
            this.ObjectType = isxp.ObjectType;
            this.ObjectGroupId = isxp.ObjectGroupId == SchConst.Groups.All ? null : isxp.ObjectGroupId;

            this.ObjectIdUrl = isxp.UrlVars.Substitution(isxp.ListObjects.GetUrl(true));
            this.OperationIdUrl = isxp.UrlVars.Substitution(isxp.ListOperations.GetUrl(true));
            this.CheckObjectsUrl = isxp.UrlVars.Substitution(isxp.CheckObjects.GetUrl(true), SchConst.UrlVars.GROUPID);

            //itt most csak az objecttype-ot helyettesítjük, mert a GroupId-t majd ha megadta az Editor ablakban
            this.ObjectEditorUrl = isxp.UrlVars.Substitution(isxp.ObjectEditor.GetUrl(true), SchConst.UrlVars.OBJECTTYPE);

            #endregion Értékek a post részére (hidden)

            #region Konzisztencia ellenőrzéshez inicializálások
            if (isxp.Manager.Buttons != null && isxp.Manager.Buttons.Any())
            {
                ButtonElement bttn = isxp.Manager.Buttons.FirstOrDefault(x => x.Name == ButtonElement.SysButtonNames.ConsistencyCheck);
                if (bttn != null)
                {
                    this.ConsistencyHeader = base.Trans(typeof(SchedulerWordCodes.iScheduler.Manager.ConsistencyTitle));
                    string stl = bttn.Style ?? ""; // a toggle button stílusánál fontos, hogy legyen ";" jel a végén
                    this.ConsistencyStyle = stl == "" ? "" : (stl + (stl.EndsWith(";") ? "" : ";"));
                    this.ConsistencyUrl = bttn.Url.GetUrl(true); //ebben nem lehet változó
                }
            }
            #endregion Konzisztencia ellenőrzéshez inicializálások
        }
        #endregion Constructor

        #region Public methods
        public SchedulerModel LoadModel() { return _LoadModel(null, 0, this); }
        public static SchedulerModel LoadModel(string sqlconnectionstring, int scheduleid) { return _LoadModel(sqlconnectionstring, scheduleid,null); }
        private static SchedulerModel _LoadModel(string sqlconnectionstring, int scheduleid, SchedulerModel existingmodel)
        {
            if (existingmodel == null) { existingmodel = new SchedulerModel(); }
            else { sqlconnectionstring = existingmodel.ConnectionString; scheduleid = existingmodel.Id; }
            if (string.IsNullOrWhiteSpace(sqlconnectionstring) || scheduleid<=0) return null;
            using (var db = new SchedulerDB(sqlconnectionstring))
            {
                Schedule schdl = db.Schedules.FirstOrDefault(x => x.Id == scheduleid);
                if (schdl == null) return null;

                existingmodel.ObjectIdValue = schdl.ScheduleObject.ObjectId;
                existingmodel.ObjectIdText = schdl.ScheduleObject.ObjectName;
                existingmodel.OperationIdValue = schdl.ScheduleOperation.OperationId;
                existingmodel.OperationIdText = schdl.ScheduleOperation.OperationName;
                existingmodel.OperationTime = schdl.OperationTime;
                existingmodel.State = schdl.State;
                existingmodel.IsExistReturnMessage = !string.IsNullOrWhiteSpace(schdl.ReturnMessage);
                existingmodel.ReturnMessage = schdl.ReturnMessage;
                existingmodel.SeriesId = schdl.ScheduleSeriesId;
                existingmodel.ObjectGroupId = schdl.ScheduleObject.ObjectGroupId;

                if (schdl.ScheduleSeriesOne == null) { existingmodel.ScheduleType = SchConst.ScheduleTypes.Single; }
                else
                {
                    existingmodel.ScheduleType = schdl.ScheduleSeriesOne.SeriesType;
                    existingmodel.SeriesName = schdl.ScheduleSeriesOne.SeriesName;
                    existingmodel.SeriesColor = schdl.ScheduleSeriesOne.SeriesColor;
                }
            }
            return existingmodel;
        }
        /// <summary>
        /// Kötelező kitöltésre figyelmeztető üzenetet ad vissza.
        /// </summary>
        /// <param name="fieldLabel"></param>
        /// <returns></returns>
        public string RequiredMessage(string fieldLabel)
        {
            return base.TransFormat(typeof(GeneralWordCodes.MLM.General.Messages.RequiredWithName), fieldLabel);
        }

        /// <summary>
        /// A hét napjainak listája. Vasárnapnál 0 a value, Hétfőnél 1.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<SelectListItem> GetDaysOfWeek()
        {
            var result = new List<SelectListItem>
            {
                new SelectListItem() { Value = "1", Text = base.Trans(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Monday)) },
                new SelectListItem() { Value = "2", Text = base.Trans(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Tuesday)) },
                new SelectListItem() { Value = "3", Text = base.Trans(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Wednesday)) },
                new SelectListItem() { Value = "4", Text = base.Trans(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Thursday)) },
                new SelectListItem() { Value = "5", Text = base.Trans(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Friday)) },
                new SelectListItem() { Value = "6", Text = base.Trans(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Saturday)) },
                new SelectListItem() { Value = "0", Text = base.Trans(typeof(SchedulerWordCodes.iScheduler.Editor.Label.Sunday)) }
            };
            return result;
        }

        /// <summary>
        /// .NET dátumformátum konvertálása Bootstrap datetimepicker formátumra
        /// </summary>
        /// <param name="dateTimeFormat">.NET DateTime formátum</param>
        /// <returns>Bootstrap DatetimePicker Formátum</returns>
        /// <remarks>DataTables-ből átemelve és átnevezve. WA.</remarks>
        public string DateTimeToBootstrapDTPF(string dateTimeFormat)
        {
            // dátum formátumok:
            // http://msdn.microsoft.com/en-us/library/8kb3ddd4%28v=vs.110%29.aspx
            // http://www.malot.fr/bootstrap-datetimepicker/

            string result = dateTimeFormat;
            result = result.Replace('m', 'i');  // perc
            result = result.Replace('h', 'x').Replace('H', 'h').Replace('x', 'H');  // óra
            result = result.Replace("MMMM", "XX").Replace("MMM", "X").Replace("MM", "xx").Replace('M', 'x'); // hónap ideiglenes csere
            result = result.Replace("XX", "MM").Replace('X', 'M').Replace("xx", "mm").Replace('x', 'm'); // hónap
            return result;
        }

        #endregion Public methods
    }
}
