using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Net.Mail;
using System.IO;
using System.Xml;
using Newtonsoft.Json;
using Foresight.Data;
using Foresight.Security.License;
using FI.FIC;
using IronIntel.Contractor.Users;
using FI.FIC.Contracts.DataObjects.Enumeration;
using System.Web;
using System.Runtime.Serialization.Formatters.Binary;

namespace IronIntel.Contractor
{
    public class IronIntelHost : IFICHost
    {
        static readonly Guid FIC_MODULE_ID = new Guid("1c6dfe25-347d-4889-ab75-73ade9190d27");
        const string FIC_MODULE_NAME = "Foresight Intelligence Center";
        const string FIC_MODULE_VERSION = "3.0";

        public string FICDbConnectionString
        {
            get
            {
                return SystemParams.FICDbConnectionString;
            }
        }

        public string FrsDbConnectionString
        {
            get
            {
                return string.Empty;
            }
        }
        public bool FICInstalled
        {
            get
            {
                return true;
            }
        }

        public bool FRSInstalled
        {
            get
            {
                return false;
            }
        }

        public static void Init()
        {
            FICHostEnvironment.SetHost(new IronIntelHost());
        }

        public byte[] GetCacheData(string key, bool ignoreExpired, ref DateTime createTime)
        {
            byte[] buffer = CacheManager.GetValue(key);
            if (buffer == null)
            {
                return null;
            }
            byte[] tmp = Foresight.Security.SecurityHelper.Decompress(buffer);
            FICCacheObject fc = new FICCacheObject();
            fc.FromBuffer(tmp);
            createTime = fc.CreateTime;
            return fc.Data;
        }

        public DataTable GetCacheDataTable(string key, bool ignoreExpired, ref DateTime createTime)
        {
            byte[] buffer = GetCacheData(key, ignoreExpired, ref createTime);
            if (buffer == null)
            {
                return null;
            }
            //FIDataTable tb = new FIDataTable();
            //tb.FillFromBuffer(buffer);
            //return FIDbAccess.ConvertDataTable(tb);
            return Deserialize(buffer) as DataTable;
        }

        public FICCompanyInfo GetCompanyInfo()
        {
            var cp = SystemParams.CustomerDetail;
            FICCompanyInfo ficcp = new FICCompanyInfo();
            ficcp.ID = cp.ID;
            ficcp.Name = cp.Name;

            return ficcp;
        }

        public CompanyLic GetLicense()
        {
            IronIntel.Services.LicenseInfo lic = SystemParams.GetLicense();
            if (lic == null)
            {
                return null;
            }
            CompanyLic ci = new CompanyLic();
            ci.CompanyID = SystemParams.CompanyID;
            ci.CompanyName = SystemParams.CustomerDetail.Name;

            Foresight.Security.License.LicenseInfo li = new LicenseInfo();
            ci.Licenses.Add(li);
            li.CompanyID = ci.CompanyID;
            li.CompanyName = ci.CompanyName;
            li.Expiration = lic.ExpireDate;
            li.ID = Guid.Empty;
            li.StartDate = lic.StartDate;
            li.ModuleID = FIC_MODULE_ID;
            li.ModuleName = FIC_MODULE_NAME;
            li.Version = FIC_MODULE_VERSION;

            foreach (var item in lic.Items)
            {
                var prop = ConvertLicenseItem(item);
                if (prop != null)
                {
                    li.AddtionalPropertes.Add(prop);
                }
            }

            return ci;
        }

        private LicenseAddtionalPropertyObj ConvertLicenseItem(Services.LicenseItem item)
        {
            if (item == null)
                return null;
            switch (item.Key)
            {
                case "ColumnLineCombChart":
                    return new LicenseAddtionalPropertyObj { Key = "ColumnLineCombChart", Value = item.Value, Description = item.Description };
                case "ExportChartToXPS":
                    return new LicenseAddtionalPropertyObj { Key = "ExportChartToXPS", Value = item.Value, Description = item.Description };
                case "FreeChart":
                    return new LicenseAddtionalPropertyObj { Key = "FreeChart", Value = item.Value, Description = item.Description };
                case "DrilldownToURL":
                    return new LicenseAddtionalPropertyObj { Key = "DrilldownToURL", Value = item.Value, Description = item.Description };
                case "MaxCharts":
                    return new LicenseAddtionalPropertyObj { Key = "MaxCharts", Value = item.Value, Description = item.Description };
                case "MaxDataTables":
                    return new LicenseAddtionalPropertyObj { Key = "MaxDataTables", Value = item.Value, Description = item.Description };
                case "PrintChart":
                    return new LicenseAddtionalPropertyObj { Key = "PrintChart", Value = item.Value, Description = item.Description };
                case "ScatterChart":
                    return new LicenseAddtionalPropertyObj { Key = "ScatterChart", Value = item.Value, Description = item.Description };
                case "Snapshot":
                    return new LicenseAddtionalPropertyObj { Key = "Snapshot", Value = item.Value, Description = item.Description };
                case "SQLGenerator":
                    return new LicenseAddtionalPropertyObj { Key = "SQLGenerator", Value = item.Value, Description = item.Description };
                case "EmailSubscribe":
                    return new LicenseAddtionalPropertyObj { Key = "EmailSubscribe", Value = item.Value, Description = item.Description };
                    //case "MainStyle":
                    //case "MaxAdminCount":
                    //case "MaxLogins":
                    //case "MaxNormalUerCount":
                    //case "MaxReadOnlyUserCount":
            }
            return null;
        }

        public string GetResourceLock(string resourceid, int locksecond)
        {
            return SystemParams.GetResourceLock(resourceid, locksecond);
        }

        private static FICUserInfo ConvertToFICUserInfo(IronIntel.Contractor.Users.UserInfo ui)
        {
            var user = new FICUserInfo
            {
                ID = ui.ID,
                IID = ui.IID,
                Enabled = ui.Active,
                DisplayName = ui.DisplayName,
                //Mobile = ui.Mobile,
                Mobile = ui.TextAddress,
                BusinessPhone = ui.BusinessPhone,
            };
            switch (ui.UserType)
            {
                case UserTypes.Common:
                    user.UserType = FICUserTypes.Common;
                    break;
                case UserTypes.Admin:
                    user.UserType = FICUserTypes.Admin;
                    break;
                case UserTypes.Readonly:
                    user.UserType = FICUserTypes.Readonly;
                    break;
                case UserTypes.SupperAdmin:
                    user.UserType = FICUserTypes.SuperAdmin;
                    break;
                default:
                    user.UserType = FICUserTypes.Readonly;
                    break;
            }
            return user;
        }

        public FICUserInfo GetUserByIID(string useriid)
        {
            UserInfo ui = UserManagement.GetUserByIID(useriid);
            if (ui == null)
            {
                return null;
            }
            return ConvertToFICUserInfo(ui);
        }

        public FICUserInfo GetUserByLoginSessionID(string sessionid)
        {
            UserInfo ui = UserManagement.GetUserBySessionID(sessionid);
            if (ui == null)
            {
                return null;
            }
            return ConvertToFICUserInfo(ui);
        }

        public FICUserInfo GetUserByUserID(string userId)
        {
            UserInfo ui = UserManagement.GetUserByID(userId);
            if (ui == null)
            {
                return null;
            }
            return ConvertToFICUserInfo(ui);
        }

        public FICUserInfo[] GetUsers()
        {
            UserInfo[] users = UserManagement.GetUsers();
            List<FICUserInfo> ls = new List<FICUserInfo>(users.Length);
            foreach (UserInfo ui in users)
            {
                ls.Add(ConvertToFICUserInfo(ui));
            }
            return ls.ToArray();
        }

        public string GetUserEmail(string useriid)
        {
            UserInfo ui = UserManagement.GetUserByIID(useriid);
            if (ui == null)
            {
                return null;
            }
            else
            {
                return ui.ID;
            }
        }

        public void PostMessage(int category, string msg)
        {
            return;
        }

        public void ReleaseResourceLock(string lockid)
        {
            SystemParams.ReleaseResourceLock(lockid);
        }

        public void RemoveCache(string key)
        {
            CacheManager.Remove(key);
        }

        public void SendMail(MailMessage message)
        {
            try
            {
                SystemParams.SendMail("FIC", message);
            }
            catch (Exception ex)
            {
                SystemParams.WriteLog("Error", this.GetType().FullName + ".SendMail(MailMessage)", "Add fic mail to mail service failed", ex.ToString());
            }
        }

        public void SetCacheData(string key, byte[] buffer, int expirationsecond, bool slidingExpiration, DateTime createTime)
        {
            if (buffer == null)
            {
                RemoveCache(key);
                return;
            }
            FICCacheObject fc = new FICCacheObject();
            fc.Data = buffer;
            fc.CreateTime = createTime;

            byte[] tmp = Foresight.Security.SecurityHelper.Compress(fc.ToBuffer());
            CacheManager.SetValue(key, tmp, TimeSpan.FromSeconds(expirationsecond));
        }

        public void SetCacheDataTable(string key, DataTable dt, int expirationsecond, bool slidingExpiration, DateTime createTime)
        {
            if (dt == null)
            {
                RemoveCache(key);
            }
            else
            {
                //FIDataTable tb = FIDbAccess.ConvertDataTable(dt, -1);
                byte[] buffer = Serialize(dt, createTime);
                SetCacheData(key, buffer, expirationsecond, slidingExpiration, createTime);
            }
        }

        public void SubscribeMessage(int category, Action<IEnumerable<MessageInformation>> action)
        {
            return;
        }

        public void WriteLog(string logType, string category, string source, string message, string detail)
        {
            SystemParams.WriteLog(logType, category, source, message, detail);
        }

        public List<string> GetUserGroupIDByUserIID(string userIID)
        {
            return UserManagement.GetUserGroupIDByUserIID(userIID);
        }

        public FICUserInfo[] GetUsers(bool hasAdmin)
        {
            if (!hasAdmin)
            {
                return GetUsers();
            }

            UserInfo[] localusers = UserManagement.GetUsers();
            UserInfo[] foresightusers = UserManagement.GetForesightUsers();
            UserInfo[] users = localusers.Union(foresightusers).ToArray();
            List<FICUserInfo> ls = new List<FICUserInfo>(users.Length);
            foreach (UserInfo ui in users)
            {
                //if (ui.UserType == UserTypes.Admin)
                //{
                ls.Add(ConvertToFICUserInfo(ui));
                //}
            }
            return ls.ToArray();
        }

        public LoginContext GetCurrentLoginContext(HttpContext context)
        {
            string session = Site.IronIntelBasePage.GetLoginSessionID(context.Request);
            if (string.IsNullOrWhiteSpace(session))
            {
                return null;
            }

            LoginContext lc = new LoginContext();
            lc.SessionID = session;
            lc.User = GetUserByLoginSessionID(session);
            lc.LanguageID = GetLgID(context);
            return lc;
        }

        private string GetLgID(HttpContext context)
        {
            var language = context.Request.Cookies[Common.LanguageCookieName];
            if (language != null)
            {
                return language.Value;
            }
            return ResLanguage.ClientCurrentLanguage;
        }

        public string ProductEdition
        {
            get
            {
                return "General";
            }
        }

        public string FIExternalDBConnectionString
        {
            get
            {
                return string.Empty;
            }
        }

        public TimeSpan BaseUtcOffset
        {
            get
            {
                var timezone = CustomerTimeZoneInfo;
                return timezone.BaseUtcOffset;
            }
        }

        public TimeZoneInfo CustomerTimeZoneInfo
        {
            get
            {
                return SystemParams.CustomerDetail.TimeZone;
            }
        }

        public string FICommonDbConnectionString
        {
            get { return string.Empty; }
        }

        public string GetStyleDefines(string useriid)
        {
            //StringBuilder s = new StringBuilder();
            //s.Append(@"<?xml version=""1.0"" encoding=""UTF-8""?>");
            //s.Append("<root>");
            //s.Append("<Workspace><Title><Background>#ff00ff</Background><Foreground>#222222</Foreground></Title></Workspace>");
            //s.Append("<Chart><Title><Background>#333333</Background><Foreground>#444444</Foreground></Title><Board>#555555</Board></Chart>");
            //s.Append("<Board><Title><Background>#666666</Background><Foreground>#777777</Foreground></Title></Board>");
            //s.Append("</root>");
            //return s.ToString();
            Services.CustUIStyle uistyle = SystemParams.GetUIStyle(useriid);

            StringBuilder s = new StringBuilder();
            s.Append(@"<?xml version=""1.0"" encoding=""UTF-8""?>");
            s.Append("<root>");
            s.Append("<Workspace><Title><Background></Background><Foreground>#000000</Foreground></Title></Workspace>");
            s.Append("<Chart><Title><Background>" + uistyle.ChartTitleBackgroundColor + "</Background><Foreground></Foreground></Title><Board>" + uistyle.ChartBorderColor + "</Board></Chart>");
            //s.Append("<Board><Title><Background>#666666</Background><Foreground>#777777</Foreground></Title></Board>");
            s.Append("</root>");
            return s.ToString();
        }
        public Dictionary<string, string> GetAdditionalParameter()
        {
            return SystemParams.GetAdditionalParameter();
        }

        public FICUserInfo[] GetSimpleUsers(bool hasAdmin)
        {
            var users = GetUsers(hasAdmin);
            List<FICUserInfo> ls = new List<FICUserInfo>();
            foreach (var user in users)
            {
                var us = new FICUserInfo();
                us.IID = user.IID;
                us.ID = user.ID;
                us.DisplayName = user.DisplayName;
                ls.Add(us);
            }
            return ls.ToArray();
        }

        public SpecialDatabaseConnectionInfo[] GetSpecialDatabaseConnections()
        {
            const string IRONINTELMASTERDB = "10000000-0000-0000-0000-100000000000";
            const string REPORTDB = "10000000-0000-0000-0000-100000000001";
            // const string IATC = "10000000-0000-0000-0000-100000000002";

            List<SpecialDatabaseConnectionInfo> ls = new List<SpecialDatabaseConnectionInfo>();
            SpecialDatabaseConnectionInfo mast = new SpecialDatabaseConnectionInfo();
            mast.ID = IRONINTELMASTERDB;
            mast.DisplayName = "FleetView";
            mast.DatabaseType = "MSSQL";
            mast.ConnectionString = SystemParams.DataDbConnectionString;
            ls.Add(mast);

            string rptstr = SystemParams.GetIronIntelReportDataDbString();
            if (!string.IsNullOrWhiteSpace(rptstr))
            {
                SpecialDatabaseConnectionInfo rptdb = new SpecialDatabaseConnectionInfo();
                rptdb.ID = REPORTDB;
                rptdb.DisplayName = "FleetView Report";
                rptdb.DatabaseType = "MSSQL";
                rptdb.ConnectionString = rptstr;
                ls.Add(rptdb);
            }
            return ls.ToArray();
        }

        class FICCacheObject
        {
            public byte[] Data = null;
            public DateTime CreateTime = DateTime.Now;

            public byte[] ToBuffer()
            {
                byte[] rst = new byte[Data.Length + 8];
                byte[] bf1 = BitConverter.GetBytes(CreateTime.Ticks);
                Buffer.BlockCopy(bf1, 0, rst, 0, 8);
                Buffer.BlockCopy(Data, 0, rst, 8, Data.Length);

                return rst;
            }

            public void FromBuffer(byte[] buffer)
            {
                long l = BitConverter.ToInt64(buffer, 0);
                CreateTime = new DateTime(l);
                Data = new byte[buffer.Length - 8];
                Buffer.BlockCopy(buffer, 8, Data, 0, buffer.Length - 8);
            }
        }

        #region - (De)Serialize -

        private static byte[] Serialize(object obj, DateTime createtime)
        {
            if (obj == null)
            {
                return null;
            }
            var cacheObj = new RedisCacheObject
            {
                CreateTime = createtime,
                Data = obj
            };
            byte[] data;
            using (var ms = new MemoryStream())
            {
                new BinaryFormatter().Serialize(ms, cacheObj);
                data = ms.ToArray();
            }
            return data;
        }

        private static object Deserialize(byte[] buffer)
        {
            using (var ms = new MemoryStream(buffer, false))
            {
                return new BinaryFormatter().Deserialize(ms);
            }
        }

        public byte[] GetCompanyLogo()
        {
            return SystemParams.GetCompanyLOGO(SystemParams.CompanyID);
        }



        #endregion


        [Serializable]
        public class RedisCacheObject
        {
            public DateTime CreateTime { get; set; }
            public object Data { get; set; }
        }

    }

}
