using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;

namespace ShaferExample
{
    public class NalpLibConfiguration
    {
        public NalpLibConfiguration()
        {
            CustomerID = int.Parse(ConfigurationManager.AppSettings["customerID"]);
            ProductID = int.Parse(ConfigurationManager.AppSettings["productID"]);
            X = UInt32.Parse(ConfigurationManager.AppSettings["securityConstantX"]);
            Y = UInt32.Parse(ConfigurationManager.AppSettings["securityConstantY"]);
            Z = UInt32.Parse(ConfigurationManager.AppSettings["securityConstantZ"]);
            ForceReg = ConfigurationManager.AppSettings["forceReg"] == "1";
            LicenseMode = ConfigurationManager.AppSettings["licenseMode"];

            if (LicenseMode == LicenseModes.LanDaemon.ToString())
            {
                DaemonIP = ConfigurationManager.AppSettings["daemonIP"];
                DaemonPort = ConfigurationManager.AppSettings["daemonPort"];
                DaemonUser = ConfigurationManager.AppSettings["daemonUser"];
                DaemonPass = ConfigurationManager.AppSettings["daemonPass"];
            }
            else if (LicenseMode == LicenseModes.Relay.ToString())
            {
                DaemonIP = ConfigurationManager.AppSettings["relayIp"];
                DaemonPort = ConfigurationManager.AppSettings["relayPort"];
            }
            else if (LicenseMode == LicenseModes.Passive.ToString())
            {
                ClientID = ConfigurationManager.AppSettings["clientId"];
                ForceReg = false;
            }
        }

        public bool ForceReg { get; }
        public string ClientID { get; }
        public string LicenseMode { get; }

        public string DaemonIP { get; }
        public string DaemonPort { get; }
        public string DaemonUser { get; }
        public string DaemonPass { get; }

        public int CustomerID { get; }
        public int ProductID { get; }
        public UInt32 X { get; }
        public UInt32 Y { get; }
        public UInt32 Z { get; }

        public enum LicenseModes
        {
            Internet,
            Relay,
            LanDaemon,
            Passive
        }
    }

    public class RegistrationForm
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string CompanyName { get; set; }
        public string Email { get; set; }
        public string Telephone { get; set; }
    }

    public class Feature
    {
        public string Name { get; set; }
        public bool Value
        {
            get { return _value; }
            set
            {
                _value = value;
                Expiration = _expiration;
            }
        }
        public DateTime? Expiration
        {
            get { return _expiration; }
            set
            {
                _expiration = value;
                var valueResult = this.Value;
                var result = string.Empty;
                if (_expiration.HasValue)
                {
                    if (_expiration.Value < DateTime.Now)
                    {
                        valueResult = false;
                        result = "Expired";
                    }
                    else
                    {
                        result = AppUtils.ExpiresIn(Expiration.Value);
                    }
                }
                this.FormatedExpirationDate = result;
                this.CalculatedValue = valueResult;
            }
        }

        public string FormatedExpirationDate { get; set; }
        public bool CalculatedValue { get; set; }

        private bool _value;
        private DateTime? _expiration;
    }

    public class ElementPool : Feature
    {
        public virtual void Copy(ElementPool ep)
        {
            Name = ep.Name;
            Value = ep.Value;
            ValueAmt = ep.ValueAmt;
            ValueMax = ep.ValueMax;
        }

        public long ValueAmt { get; set; }
        public long ValueMax { get; set; }
    }

    public class ConsumptionToken : ElementPool
    {
        public long Consumed { get; set; }
    }

    public class Agility
    {
        public string Name { get; set; }
        public string Value { get; set; }
    }

    public class FeatureExpiration
    {
        public string Name { get; set; }
        public string Type { get; set; }
        public DateTime Date { get; set; }
    }

    public class FeatureExpirationInfo
    {
        public FeatureExpirationInfo(string fieldValue)
        {
            fieldValue = fieldValue ?? string.Empty;
            IFormatProvider provider = CultureInfo.InvariantCulture.DateTimeFormat;
            List = new List<FeatureExpiration>();
            var fields = fieldValue.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var field in fields)
            {
                var pair = field.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                if (pair.Count() == 2)
                {
                    string name = pair[0];
                    string type = "N";
                    if (name.StartsWith("f."))
                    {
                        name = name.Substring(2);
                        type = "F";
                    }
                    var date = new DateTime();

                    if (DateTime.TryParseExact(pair[1], new string[] { "dd/MM/yyyy", "d/M/yyyy" }, provider, DateTimeStyles.AdjustToUniversal, out date))
                    {
                        List.Add(new FeatureExpiration() { Date = date.AddDays(1).AddSeconds(-1), Name = name, Type = type });
                    }
                }
            }
        }

        public DateTime? GetFeatureExpirationDate(string name)
        {
            return GetFeatureExpirationDate(name, "N");
        }

        public DateTime? GetFloatingFeatureExpirationDate(string name)
        {
            return GetFeatureExpirationDate(name, "F");
        }

        private DateTime? GetFeatureExpirationDate(string name, string type)
        {
            DateTime? result = null;
            var value = List.Where(x => x.Name == name && x.Type == type).FirstOrDefault();
            if (value != null)
            {
                result = value.Date;
            }
            return result;
        }

        public List<FeatureExpiration> List { get; set; }
    }

    public class Processes
    {
        public int Max { get; set; }
        public int Available { get; set; }
    }

    public class AuthData
    {
        public string Password { get; set; }
        public string Username { get; set; }
    }

    public class Message
    {
        public void CalculateValues()
        {
            var now = DateTime.Now;
            FromDate = StringToDate(From);
            ToDate = StringToDate(To);
            if (ToDate.HasValue) { ToDate = ToDate.Value.AddDays(1).AddSeconds(-1); }
            Valid = false;
            if ((FromDate.HasValue && FromDate.Value <= now) || !FromDate.HasValue)
            {
                if ((ToDate.HasValue && ToDate.Value >= now) || !ToDate.HasValue)
                {
                    Valid = true;
                }
            }
        }

        private DateTime? StringToDate(string value)
        {
            IFormatProvider provider = CultureInfo.InvariantCulture.DateTimeFormat;
            DateTime date;
            DateTime? result = null;
            if (DateTime.TryParseExact(value, new string[] { "dd/MM/yyyy", "d/M/yyyy" }, provider, DateTimeStyles.AdjustToUniversal, out date))
            {
                result = date;
            }
            return result;
        }

        public string From { get; set; }
        public string To { get; set; }
        public string Msg { get; set; }

        public DateTime? FromDate { get; set; }
        public DateTime? ToDate { get; set; }
        public bool Valid { get; set; }
    }

    public class MessagesInfo
    {
        public MessagesInfo(string fieldValue)
        {
            fieldValue = fieldValue ?? string.Empty;
            fieldValue = fieldValue.Replace(";", ",");
            try
            {
                List = JsonConvert.DeserializeObject<List<Message>>(fieldValue);
            }
            catch { }
            List = List ?? new List<Message>();
            List.ForEach(x => x.CalculateValues());
        }

        public List<Message> CurrentMessages
        {
            get
            {
                return List.OrderByDescending(x => x.Valid).ToList();
            }
        }

        public List<Message> List { get; set; }
    }
}
