using Foresight;
using Foresight.Data;
using Foresight.Fleet.Services.User;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace IronIntel.Contractor.Users
{
    public static class UserParams
    {
        private const string _AutoRecenterMap = "AutoRecenterMap";
        private const string _ShowJSTooltip = "ShowJSTooltip";
        private const string _BaseMap = "BaseMap";
        private const string _MapViewContratorID = "MapViewContratorID";
        private const string _MapAlertLayer = "MapAlertLayer";
        public const string _SystemStyleID = "SystemStyleID";
        private const string _MapRefreshInterval = "MapRefreshInterval";
        private const string _AssetDefaultSearch = "AssetDefaultSearch";
        private const string _JobSiteDefaultSearch = "JobSiteDefaultSearch";
        private const string _AssetGroupDefaultSearch = "AssetGroupDefaultSearch";
        private const string _UnShownMachines = "UnShownMachines";
        private const string _UnShownJobsites = "UnShownJobsites";
        private const string _UnShownJobsiteMachines = "UnShownJobsiteMachines";
        private const string _Onroad = "Onroad";
        private const string _Attachment = "Attachment";
        private const string _ExcludeNoLocation = "ExcludeNoLocation";

        private const string _MapViewSearches = "MapViewSearches";
        private const string _LandingPage = "LandingPage";

        public static UserParamInfo GetUserParams(string sessionid, string useriid)
        {
            UserParamInfo userParams = new UserParamInfo();
            string sql = "select PARAMNAME,PARAMVALUE from USERSPARAM where USERIID={0} ";
            FIDbAccess db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(sql, useriid);

            foreach (DataRow dr in dt.Rows)
            {
                string name = FIDbAccess.GetFieldString(dr["PARAMNAME"], "");
                string value = FIDbAccess.GetFieldString(dr["PARAMVALUE"], "");
                switch (name)
                {
                    case _AutoRecenterMap:
                        userParams.AutoRecenterMap = Helper.IsTrue(value);
                        break;
                    case _ShowJSTooltip:
                        userParams.ShowJSTooltip = Helper.IsTrue(value);
                        break;
                    case _BaseMap:
                        userParams.BaseMap = value;
                        break;
                    case _MapViewContratorID:
                        userParams.MapViewContratorID = value;
                        break;
                    case _MapAlertLayer:
                        userParams.MapAlertLayer = value;
                        break;
                    case _SystemStyleID:
                        userParams.SystemStyleID = value;
                        break;
                    case _AssetDefaultSearch:
                        userParams.AssetDefaultSearch = value;
                        break;
                    case _JobSiteDefaultSearch:
                        userParams.JobSiteDefaultSearch = value;
                        break;
                    case _AssetGroupDefaultSearch:
                        userParams.AssetGroupDefaultSearch = value;
                        break;
                    case _UnShownMachines:
                        userParams.UnShownMachines = value.Split(',');
                        break;
                    case _UnShownJobsites:
                        userParams.UnShownJobsites = value.Split(',');
                        break;
                    case _UnShownJobsiteMachines:
                        userParams.UnShownJobsiteMachines = value.Split(',');
                        break;
                    case _Onroad:
                        userParams.Onroad = int.Parse(value);
                        break;
                    case _Attachment:
                        userParams.Attachment = int.Parse(value);
                        break;
                    case _ExcludeNoLocation:
                        userParams.ExcludeNoLocation = int.Parse(value) == 1;
                        break;
                    case _LandingPage:
                        userParams.LandingPage = value;
                        break;
                }
            }
            userParams.MapViewSearches = GetMapViewSearches(sessionid, useriid);

            //if (string.IsNullOrEmpty(userParams.SystemStyleID))
            //{
            //    var defaultStyle = SystemParams.GetUIStyle();//获取系统默认Style
            //    userParams.SystemStyleID = defaultStyle.UIStyleID.ToString();
            //}
            string intervalStr = SystemParams.GetStringParam(_MapRefreshInterval);
            int interval = 0;
            if (!string.IsNullOrWhiteSpace(intervalStr) && int.TryParse(intervalStr, out interval) && interval > 60)
                userParams.MapRefreshInterval = interval;
            else
                userParams.MapRefreshInterval = 60;
            userParams.MachineIconURL = SystemParams.MachineTypeMapViewIconUrl;

            var uc = FleetServiceClientHelper.CreateClient<UserQueryClient>();
            userParams.PreferredLanguage = uc.GetUserPreferredLanguageByIID(useriid);
            userParams.TimeZone = uc.GetUserTimeZoneByIID(useriid);

            return userParams;
        }

        public static void SetUserParams(string useriid, UserParamInfo userParams)
        {
            const string SQL = @"if exists(select 1 from USERSPARAM where USERIID={0} and PARAMNAME={1})  
                    update USERSPARAM set PARAMVALUE = {2}, BINCONTENT = null where USERIID = {0} and PARAMNAME = {1}
                    else insert into USERSPARAM(USERIID, PARAMNAME, PARAMVALUE, BINCONTENT) values({0},{1},{2},null) ";
            const string SQL_Delete = @"delete from USERSPARAM where USERIID={0} and PARAMNAME={1} ";

            FIDbAccess db = SystemParams.GetDbInstance();
            db.ExecSQL(SQL, useriid, _AutoRecenterMap, userParams.AutoRecenterMap ? "true" : "false");
            db.ExecSQL(SQL, useriid, _ShowJSTooltip, userParams.ShowJSTooltip ? "true" : "false");

            if (!string.IsNullOrEmpty(userParams.BaseMap))
                db.ExecSQL(SQL, useriid, _BaseMap, userParams.BaseMap);
            else
                db.ExecSQL(SQL_Delete, useriid, _BaseMap);

            if (!string.IsNullOrEmpty(userParams.MapViewContratorID))
                db.ExecSQL(SQL, useriid, _MapViewContratorID, userParams.MapViewContratorID);
            else
                db.ExecSQL(SQL_Delete, useriid, _MapViewContratorID);

            if (!string.IsNullOrEmpty(userParams.MapAlertLayer))
                db.ExecSQL(SQL, useriid, _MapAlertLayer, userParams.MapAlertLayer);
            else
                db.ExecSQL(SQL_Delete, useriid, _MapAlertLayer);

            if (!string.IsNullOrEmpty(userParams.SystemStyleID))
                db.ExecSQL(SQL, useriid, _SystemStyleID, userParams.SystemStyleID);
            else
                db.ExecSQL(SQL_Delete, useriid, _SystemStyleID);

            if (!string.IsNullOrEmpty(userParams.AssetDefaultSearch))
                db.ExecSQL(SQL, useriid, _AssetDefaultSearch, userParams.AssetDefaultSearch);
            else
                db.ExecSQL(SQL_Delete, useriid, _AssetDefaultSearch);

            if (!string.IsNullOrEmpty(userParams.JobSiteDefaultSearch))
                db.ExecSQL(SQL, useriid, _JobSiteDefaultSearch, userParams.JobSiteDefaultSearch);
            else
                db.ExecSQL(SQL_Delete, useriid, _JobSiteDefaultSearch);

            if (!string.IsNullOrEmpty(userParams.AssetGroupDefaultSearch))
                db.ExecSQL(SQL, useriid, _AssetGroupDefaultSearch, userParams.AssetGroupDefaultSearch);
            else
                db.ExecSQL(SQL_Delete, useriid, _AssetGroupDefaultSearch);

            if (userParams.UnShownMachines != null && userParams.UnShownMachines.Length > 0)
                db.ExecSQL(SQL, useriid, _UnShownMachines, string.Join(",", userParams.UnShownMachines));
            else
                db.ExecSQL(SQL_Delete, useriid, _UnShownMachines);

            if (userParams.UnShownJobsites != null && userParams.UnShownJobsites.Length > 0)
                db.ExecSQL(SQL, useriid, _UnShownJobsites, string.Join(",", userParams.UnShownJobsites));
            else
                db.ExecSQL(SQL_Delete, useriid, _UnShownJobsites);

            if (userParams.UnShownJobsiteMachines != null && userParams.UnShownJobsiteMachines.Length > 0)
                db.ExecSQL(SQL, useriid, _UnShownJobsiteMachines, string.Join(",", userParams.UnShownJobsiteMachines));
            else
                db.ExecSQL(SQL_Delete, useriid, _UnShownJobsiteMachines);

            if (userParams.Onroad >= 0)
                db.ExecSQL(SQL, useriid, _Onroad, userParams.Onroad);
            else
                db.ExecSQL(SQL_Delete, useriid, _Onroad);

            if (userParams.Attachment >= 0)
                db.ExecSQL(SQL, useriid, _Attachment, userParams.Attachment);
            else
                db.ExecSQL(SQL_Delete, useriid, _Attachment);

            db.ExecSQL(SQL, useriid, _ExcludeNoLocation, userParams.ExcludeNoLocation ? 1 : 0);

            if (!string.IsNullOrEmpty(userParams.LandingPage))
                db.ExecSQL(SQL, useriid, _LandingPage, userParams.LandingPage);
            else
                db.ExecSQL(SQL_Delete, useriid, _LandingPage);

        }

        public static string GetStringParameter(string useriid, string paramname)
        {
            const string SQL = "select PARAMVALUE from USERSPARAM where USERIID={0} and PARAMNAME={1}";

            FIDbAccess db = SystemParams.GetDbInstance();
            object obj = db.GetRC1BySQL(SQL, useriid, paramname);
            return FIDbAccess.GetFieldString(obj, string.Empty);
        }

        public static void SetStringParameter(string useriid, string paramname, string value)
        {
            const string SQL = @"if exists(select 1 from USERSPARAM where USERIID={0} and PARAMNAME={1})  
                    update USERSPARAM set PARAMVALUE = {2}, BINCONTENT = null where USERIID = {0} and PARAMNAME = {1}
                    else insert into USERSPARAM(USERIID, PARAMNAME, PARAMVALUE, BINCONTENT) values({0},{1},{2},null) ";

            FIDbAccess db = SystemParams.GetDbInstance();
            db.ExecSQL(SQL, useriid, paramname, value);
        }

        public static byte[] GetBinaryParameter(string useriid, string paramname)
        {
            const string SQL = "select BINCONTENT from USERSPARAM where USERIID={0} and PARAMNAME={1}";

            FIDbAccess db = SystemParams.GetDbInstance();
            object obj = db.GetRC1BySQL(SQL, useriid, paramname);
            return FIDbAccess.GetFieldBytes(obj);
        }

        public static void SetBinaryParameter(string useriid, string paramname, byte[] buffer)
        {
            const string SQL = @"if exists(select 1 from USERSPARAM where USERIID={0} and PARAMNAME={1})  
                     update USERSPARAM set PARAMVALUE = '', BINCONTENT = {2} where USERIID = {0} and PARAMNAME = {1}
                     else insert into USERSPARAM(USERIID, PARAMNAME, PARAMVALUE, BINCONTENT) values({0},{1},'',{2})";


            FIDbAccess db = SystemParams.GetDbInstance();
            db.ExecSQL(SQL, useriid, paramname, buffer);
        }

        private static MapViewSearchItem[] GetMapViewSearches(string sessionid, string useriid)
        {
            try
            {
                string xmlstr = FleetServiceClientHelper.CreateClient<UserProfileProvider>(sessionid).GetUserParams(SystemParams.CompanyID, useriid, _MapViewSearches);
                List<MapViewSearchItem> searches = MapViewSearcheHelper.FromXML(xmlstr);
                return searches.OrderByDescending(s => s.IsDefault).ThenBy(s => s.Name).ToArray();
            }
            catch
            {
                return new MapViewSearchItem[0];
            }
        }

        public static MapViewSearchItem[] SaveMapViewSearch(string sessionid, string useriid, MapViewSearchItem search)
        {
            var client = FleetServiceClientHelper.CreateClient<UserProfileProvider>(sessionid);
            string xmlstr = client.GetUserParams(SystemParams.CompanyID, useriid, _MapViewSearches);
            List<MapViewSearchItem> searches = MapViewSearcheHelper.FromXML(xmlstr);

            var item = searches.FirstOrDefault((s) => s.Name.Equals(search.Name, StringComparison.OrdinalIgnoreCase));
            if (item != null)//如果已经存在,先移除
                searches.Remove(item);

            if (search.IsDefault)
            {
                foreach (var s in searches)
                {
                    s.IsDefault = false;
                }
            }
            searches.Add(search);

            client.SetUserParam(SystemParams.CompanyID, useriid, _MapViewSearches, MapViewSearcheHelper.ToXml(searches).InnerXml);
            return searches.OrderByDescending(s => s.IsDefault).ThenBy(s => s.Name).ToArray();
        }

        private static MapViewSearchItem[] AddSearchItem(MapViewSearchItem[] searches, string search, bool isDefault)
        {
            List<MapViewSearchItem> result = null;
            if (searches != null)
            {
                result = searches.ToList();
                var item = result.FirstOrDefault((s) => s.Name.Equals(search, StringComparison.OrdinalIgnoreCase));
                if (item != null)//already exists, remove it
                    result.Remove(item);
            }
            else
                result = new List<MapViewSearchItem>();
            if (isDefault)
            {
                foreach (var s in result)
                {
                    s.IsDefault = false;
                }
            }
            result.Add(new MapViewSearchItem() { Name = search, IsDefault = isDefault });
            return result.ToArray();
        }

        public static MapViewSearchItem[] DeleteMapViewSearch(string sessionid, string useriid, string searchName)
        {
            var client = FleetServiceClientHelper.CreateClient<UserProfileProvider>(sessionid);
            string xmlstr = client.GetUserParams(SystemParams.CompanyID, useriid, _MapViewSearches);
            List<MapViewSearchItem> searches = MapViewSearcheHelper.FromXML(xmlstr);
            var item = searches.FirstOrDefault((s) => s.Name.Equals(searchName, StringComparison.OrdinalIgnoreCase));
            if (item != null)// remove it
                searches.Remove(item);

            client.SetUserParam(SystemParams.CompanyID, useriid, _MapViewSearches, MapViewSearcheHelper.ToXml(searches).InnerXml);
            return searches.OrderByDescending(s => s.IsDefault).ThenBy(s => s.Name).ToArray();
        }

        private static MapViewSearchItem[] RemoveSearchItem(MapViewSearchItem[] searches, string search)
        {
            if (searches == null) return null;
            List<MapViewSearchItem> result = searches.ToList();
            var item = result.FirstOrDefault((s) => s.Name.Equals(search, StringComparison.OrdinalIgnoreCase));
            if (item != null)// remove it
                result.Remove(item);
            return result.ToArray();
        }
    }
    public class UserParamInfo
    {
        public bool AutoRecenterMap { get; set; } = false;
        public bool ShowJSTooltip { get; set; } = false;
        public string BaseMap { get; set; }
        public string MapViewContratorID { get; set; }
        public string MapAlertLayer { get; set; }
        public string SystemStyleID { get; set; }
        public int MapRefreshInterval { get; set; }
        public string MachineIconURL { get; set; }
        public string AssetDefaultSearch { get; set; }
        public string JobSiteDefaultSearch { get; set; }
        public string AssetGroupDefaultSearch { get; set; }
        public string[] UnShownMachines { get; set; }
        public string[] UnShownJobsites { get; set; }
        public string[] UnShownJobsiteMachines { get; set; }
        public int Onroad { get; set; } = -1;
        public int Attachment { get; set; } = 0;
        public bool ExcludeNoLocation { get; set; } = true;

        public MapViewSearchItem[] MapViewSearches { get; set; }
        public string LandingPage { get; set; }
        public string PreferredLanguage { get; set; }
        public string TimeZone { get; set; }
    }

    public class MapViewSearcheHelper
    {
        public static List<MapViewSearchItem> FromXML(string xmlstr)
        {
            List<MapViewSearchItem> searches = new List<MapViewSearchItem>();
            if (!string.IsNullOrEmpty(xmlstr))
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xmlstr);
                XmlNode ch = doc.DocumentElement.FirstChild;
                if (string.Compare(ch.Name, "Searches", true) == 0)
                {
                    foreach (XmlNode node in ch.ChildNodes)
                    {
                        searches.Add(FromXml(node));
                    }
                }
            }
            return searches;
        }

        private static MapViewSearchItem FromXml(XmlNode node)
        {
            MapViewSearchItem item = new MapViewSearchItem();
            foreach (XmlNode ch in node.ChildNodes)
            {
                if (string.Compare(ch.Name, "Name", true) == 0)
                    item.Name = ch.InnerText;
                else if (string.Compare(ch.Name, "IsDefault", true) == 0)
                    item.IsDefault = Helper.IsTrue(ch.InnerText);
                else if (string.Compare(ch.Name, "Onroad", true) == 0)
                    item.Onroad = Convert.ToInt32(ch.InnerText);
                else if (string.Compare(ch.Name, "Attachment", true) == 0)
                    item.Attachment = Convert.ToInt32(ch.InnerText);
                else if (string.Compare(ch.Name, "AssetDefaultSearch", true) == 0)
                    item.AssetDefaultSearch = ch.InnerText;
                else if (string.Compare(ch.Name, "JobSiteDefaultSearch", true) == 0)
                    item.JobSiteDefaultSearch = ch.InnerText;
                else if (string.Compare(ch.Name, "AssetGroupDefaultSearch", true) == 0)
                    item.AssetGroupDefaultSearch = ch.InnerText;
                else if (string.Compare(ch.Name, "ExcludeNoLocation", true) == 0)
                    item.ExcludeNoLocation = Convert.ToInt32(ch.InnerText) == 1;
                else if (string.Compare(ch.Name, "UnShownMachines", true) == 0)
                    item.UnShownMachines = ch.InnerText.Split(',');
                else if (string.Compare(ch.Name, "UnShownJobsites", true) == 0)
                    item.UnShownJobsites = ch.InnerText.Split(',');
                else if (string.Compare(ch.Name, "UnShownJobsiteMachines", true) == 0)
                    item.UnShownJobsiteMachines = ch.InnerText.Split(',');

            }
            return item;
        }
        public static XmlDocument ToXml(List<MapViewSearchItem> searches)
        {
            XmlDocument doc = XmlHelper.CreateXmlDocument();
            XmlNode node = XmlHelper.AppendChildNode(doc.DocumentElement, "Searches", "");
            if (searches != null && searches.Count > 0)
            {
                foreach (var search in searches)
                {
                    var sn = AddSubNode(node, "Search", "");

                    AddSubNode(sn, "Name", search.Name);
                    AddSubNode(sn, "IsDefault", search.IsDefault ? "Yes" : "No");
                    if (!string.IsNullOrEmpty(search.AssetDefaultSearch))
                        AddSubNode(sn, "AssetDefaultSearch", search.AssetDefaultSearch);
                    if (!string.IsNullOrEmpty(search.JobSiteDefaultSearch))
                        AddSubNode(sn, "JobSiteDefaultSearch", search.JobSiteDefaultSearch);
                    if (!string.IsNullOrEmpty(search.AssetGroupDefaultSearch))
                        AddSubNode(sn, "AssetGroupDefaultSearch", search.AssetGroupDefaultSearch);
                    AddSubNode(sn, "Onroad", search.Onroad.ToString());
                    AddSubNode(sn, "Attachment", search.Attachment.ToString());
                    AddSubNode(sn, "ExcludeNoLocation", search.ExcludeNoLocation ? "1" : "0");
                    if (search.UnShownMachines != null && search.UnShownMachines.Length > 0)
                        AddSubNode(sn, "UnShownMachines", string.Join(",", search.UnShownMachines));
                    if (search.UnShownJobsites != null && search.UnShownJobsites.Length > 0)
                        AddSubNode(sn, "UnShownJobsites", string.Join(",", search.UnShownJobsites));
                    if (search.UnShownJobsiteMachines != null && search.UnShownJobsiteMachines.Length > 0)
                        AddSubNode(sn, "UnShownJobsiteMachines", string.Join(",", search.UnShownJobsiteMachines));
                }
            }
            return doc;
        }

        private static XmlNode AddSubNode(XmlNode parent, string nodename, string innertext)
        {
            XmlNode node = parent.OwnerDocument.CreateNode(XmlNodeType.Element, nodename, string.Empty);
            if (!string.IsNullOrEmpty(innertext))
            {
                node.InnerText = innertext;
            }
            parent.AppendChild(node);
            return node;
        }
    }

    public class MapViewSearchItem
    {
        public string Name { get; set; }
        public bool IsDefault { get; set; }

        public int Onroad { get; set; } = -1;
        public int Attachment { get; set; } = 0;
        public string AssetDefaultSearch { get; set; } = "";
        public string JobSiteDefaultSearch { get; set; } = "";
        public string AssetGroupDefaultSearch { get; set; } = "";
        public bool ExcludeNoLocation { get; set; } = true;
        public string[] UnShownMachines { get; set; }
        public string[] UnShownJobsites { get; set; }
        public string[] UnShownJobsiteMachines { get; set; }
    }
}