using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Web;
using Newtonsoft.Json;
using IronIntel.Contractor.MapView;
using IronIntel.Contractor.Users;
using Foresight.ServiceModel;
using Foresight.Fleet.Services.Attachment;
using Foresight.Fleet.Services.JobSite;
using Foresight.Fleet.Services.MapView;
using System.Net;
using IronIntel.Contractor.iisitebase;
using Foresight.Fleet.Services.Asset;
using System.Text.RegularExpressions;

namespace IronIntel.Contractor.Site.MapView
{
    public class MapViewHandler : IronIntelHttpHandlerBase
    {
        public MapViewHandler(HttpContext context)
            : base(context)
        {
        }

        public override void ProcessRequest()
        {
            object result = "\"OK\"";
            string methidName = Context.Request.Params["MethodName"];
            try
            {
                switch (methidName)
                {
                    case "GetAssets":
                        result = GetAssets();
                        break;
                    case "GetAssetBasicInfos":
                        result = GetAssetBasicInfos();
                        break;
                    case "GetAssetBasicInfoByAssets":
                        result = GetAssetBasicInfoByAssets();
                        break;
                    case "GetAssetGroups":
                        result = GetAssetGroups();
                        break;
                    case "GetContractors":
                        result = GetContractors();
                        break;
                    case "GetHistoryLocation":
                        result = GetHistoryLocation();
                        break;
                    case "GetJobSites":
                        result = GetJobSites();
                        break;
                    case "GetCompanyLocations":
                        result = GetCompanyLocations();
                        break;
                    case "GetMapAlertLayers":
                        result = GetMapAlertLayers();
                        break;
                    case "GetUserParams":
                        result = GetUserParams();
                        break;
                    case "SetUserParams":
                        result = SetUserParams();
                        break;
                    case "GetServerVersion":
                        result = GetServerVersion();
                        break;
                    case "GetContacts":
                        result = GetContacts();
                        break;
                    case "GetMachineContacts":
                        result = GetMachineContacts();
                        break;
                    case "GetJobsiteContacts":
                        result = GetJobsiteContacts();
                        break;
                    case "SendEmails":
                        result = SendEmails();
                        break;
                    case "SaveMapViewSearch":
                        result = SaveMapViewSearch();
                        break;
                    case "DeleteMapViewSearch":
                        result = DeleteMapViewSearch();
                        break;
                    case "GetShapeFileInfos":
                        result = GetShapeFileInfos();
                        break;
                    case "GetShapeData":
                        result = GetShapeData();
                        break;
                    case "ImportShape":
                        result = ImportShape();
                        break;
                    case "UpdateShapeName":
                        result = UpdateShapeName();
                        break;
                    case "DeleteShape":
                        result = DeleteShape();
                        break;
                    case "GetAssetByID":
                        result = GetAssetByID();
                        break;
                    case "RequestVideo":
                        result = RequestVideo();
                        break;
                    case "GetAssetTripLins":
                        result = GetAssetTripLins();
                        break;
                    case "GetLocationPrimaryDataSource":
                        result = GetLocationPrimaryDataSource();
                        break;
                    case "GetAssetMapAttachments":
                        result = GetAssetMapAttachments();
                        break;
                    case "GetNowFormatDate":
                        result = GetNowFormatDate();
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                SystemParams.WriteLog("error", "MapViewHandler", ex.Message, ex.ToString());
                throw ex;
            }
            string json = JsonConvert.SerializeObject(result, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
            Context.Response.ContentType = "application/json";
            Context.Response.Write(json);
            Context.Response.End();
        }

        private string GetServerVersion()
        {
            string serverVersion = SystemParams.GetVersion();
            return serverVersion;
        }

        const char SPLITCHAR170 = (char)170;
        const char SPLITCHAR171 = (char)171;
        private object GetAssets()
        {
            AssetMapViewPinItem[] assets = null;
            if (LoginSession != null)
            {
                var clientdata = Context.Request.Params["ClientData"];

                GetMachineParameterItem p = JsonConvert.DeserializeObject<GetMachineParameterItem>(clientdata);
                p.SearchText = HttpUtility.HtmlDecode(p.SearchText);

                MachineAlertViewQueryParameter viewqueryparam = null;
                if (!string.IsNullOrWhiteSpace(p.ViewID))
                {
                    viewqueryparam = ConvertToMachineAlertViewQueryParameter(p);
                }

                if (!SystemParams.IsDealer)
                    assets = AssetMapViewManagement.GetAssets(LoginSession.SessionID, p.ContractorID, LoginSession.User.UID, p.SearchText, p.Onroad, viewqueryparam, !p.ExcludeNoLocation, p.Attachment);
                else
                    assets = AssetMapViewManagement.GetDealerAssets(LoginSession.SessionID, p.ContractorID, LoginSession.User.UID, p.SearchText, p.Onroad, viewqueryparam, !p.ExcludeNoLocation, p.Attachment);

                SystemParams.WriteRefreshLog(LoginSession.User.UID, UserHostAddress, "Assets", p.IsAutoRefresh ? "Auto" : "Manual");
            }
            else
                assets = new AssetMapViewPinItem[0];

            List<string> results = new List<string>();
            foreach (var r in assets)
            {
                if (r is AssetMapViewPinItemClient)
                {
                    AssetMapViewPinItemClient rc = r as AssetMapViewPinItemClient;
                    var companyinfo = rc.CompanyID + SPLITCHAR170 + rc.CompanyName;
                    results.Add(companyinfo + SPLITCHAR171 + r.ToString());
                }
                else
                    results.Add(r.ToString());
            }

            return results.ToArray();

            //return assets;
        }

        private MapViewAssetItem[] GetAssetBasicInfos()
        {//获取用户有权的机器的基础信息，缓存在前端
            MapViewAssetItem[] assets = null;
            if (LoginSession != null)
            {
                var clientdata = Context.Request.Params["ClientData"];

                clientdata = HttpUtility.HtmlDecode(clientdata);
                string[] ps = JsonConvert.DeserializeObject<string[]>(clientdata);

                if (!SystemParams.IsDealer)
                    assets = AssetMapViewManagement.GetAssetBasicInfos(LoginSession.SessionID, ps[0], LoginSession.User.UID);
                else
                    assets = AssetMapViewManagement.GetDealerAssetBasicInfos(LoginSession.SessionID, ps[0], LoginSession.User.UID);
            }
            else
                assets = new MapViewAssetItem[0];

            return assets;
        }

        private MapViewAssetItem[] GetAssetBasicInfoByAssets()
        {//获取用户有权的机器的基础信息，缓存在前端
            MapViewAssetItem[] assets = null;
            if (LoginSession != null)
            {
                var clientdata = Context.Request.Params["ClientData"];

                clientdata = HttpUtility.HtmlDecode(clientdata);
                string[] ps = JsonConvert.DeserializeObject<string[]>(clientdata);
                long[] assetids = JsonConvert.DeserializeObject<long[]>(ps[1]);

                if (assetids.Length > 0)
                    assets = AssetMapViewManagement.GetAssetItemsByAssets(LoginSession.SessionID, ps[0], LoginSession.User.UID, assetids);
            }
            else
                assets = new MapViewAssetItem[0];

            return assets;
        }

        private AssetGroupViewItem[] GetAssetGroups()
        {
            AssetGroupViewItem[] groups = null;
            if (LoginSession != null)
            {
                var clientdata = Context.Request.Params["ClientData"];

                GetMachineParameterItem p = JsonConvert.DeserializeObject<GetMachineParameterItem>(clientdata);
                p.SearchText = HttpUtility.HtmlDecode(p.SearchText);

                string companyid = p.ContractorID;
                if (string.IsNullOrEmpty(companyid))
                    companyid = SystemParams.CompanyID;

                List<AssetGroupViewItem> temp = new List<AssetGroupViewItem>();
                if (!SystemParams.IsDealer)
                    groups = AssetMapViewManagement.GetAssetGroups(LoginSession.SessionID, companyid, LoginSession.User.UID, p.SearchText);
                else
                    groups = AssetMapViewManagement.GetDealerAssetGroups(LoginSession.SessionID, companyid, LoginSession.User.UID, p.SearchText);
                temp.AddRange(groups);

                AssetGroupViewItem eg = new AssetGroupViewItem() { ID = "-1", Name = SystemParams.GetTextByKey(GetLanguageCookie(), "P_MV_NOASSETGROUPASSIGNED", "No Asset Group Assigned") };
                temp.Add(eg);
                groups = temp.ToArray();
            }
            else
                groups = new AssetGroupViewItem[0];

            return groups;
        }

        private MachineAlertViewQueryParameter ConvertToMachineAlertViewQueryParameter(GetMachineParameterItem machineparam)
        {
            MachineAlertViewQueryParameter viewqueryparam = new MachineAlertViewQueryParameter();
            viewqueryparam.ViewID = machineparam.ViewID;
            if (machineparam.Layers != null && machineparam.Layers.Length > 0)
            {
                List<MachineAlertLayerQueryParameter> layerlist = new List<MachineAlertLayerQueryParameter>();
                foreach (var la in machineparam.Layers)
                {
                    MachineAlertLayerQueryParameter layer = new MachineAlertLayerQueryParameter();
                    layer.LayerID = la.ID;
                    if (la.Pivots != null && la.Pivots.Length > 0)
                    {
                        foreach (var pa in la.Pivots)
                        {
                            if (pa.IsCriteriaSQL)
                                layer.CriteriaParameters.Add(pa.Name, pa.ParameterValue);
                            else
                                layer.AlertDescriptionParameters.Add(pa.Name, pa.ParameterValue);
                        }
                    }

                    layerlist.Add(layer);
                }
                viewqueryparam.Layers.AddRange(layerlist);
            }
            return viewqueryparam;

        }

        private AssetDetailViewItem GetAssetByID()
        {
            if (LoginSession != null)
            {
                var clientdata = Context.Request.Params["ClientData"];
                string[] ps = JsonConvert.DeserializeObject<string[]>(clientdata);
                long assetid = 0;
                long.TryParse(ps[0], out assetid);

                string companyid = ps[1];
                if (string.IsNullOrEmpty(companyid))
                    companyid = SystemParams.CompanyID;

                return AssetMapViewManagement.GetAssetDetailItem(LoginSession.SessionID, companyid, assetid);
            }
            return null;
        }

        private KeyValuePair<string, string>[] GetContractors()
        {
            KeyValuePair<string, string>[] result;
            if (LoginSession != null)
            {
                result = MapViewer.GetContractors(LoginSession.User.UID);
                result = result.OrderBy(kv => kv.Value).ToArray();
            }
            else
            {
                result = new KeyValuePair<string, string>[0];
            }
            return result;
        }

        private AssetLocationHistoryViewItem GetHistoryLocation()
        {
            AssetLocationHistoryViewItem item = null;
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                string[] ps = p.Split(';');
                //if (ps.Length != 6) return item;
                DateTime dtFrom = DateTime.Now;
                DateTime dtTo = DateTime.Now;
                if (!DateTime.TryParse(ps[1], out dtFrom) || !DateTime.TryParse(ps[2], out dtTo))
                    return item;
                string companyid = ps[3].Trim();//companyid
                bool notShow00loc = ps[4] == "1";
                string datasource = "";
                if (ps.Length > 5)
                    datasource = ps[5];

                item = AssetMapViewManagement.GetMachineLocationHistory(LoginSession.SessionID, ps[0], dtFrom, dtTo, companyid, notShow00loc, datasource);
            }
            else
            {
                item = new AssetLocationHistoryViewItem();
            }
            return item;
        }

        private AssetTripItem[] GetAssetTripLins()
        {
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                string[] ps = p.Split(';');
                //if (ps.Length != 6) return item;
                DateTime dtFrom = DateTime.Now;
                DateTime dtTo = DateTime.Now;
                if (!DateTime.TryParse(ps[1], out dtFrom) || !DateTime.TryParse(ps[2], out dtTo))
                    return new AssetTripItem[0];
                string companyid = ps[3].Trim();//companyid
                if (string.IsNullOrEmpty(companyid))
                    companyid = SystemParams.CompanyID;

                var client = FleetServiceClientHelper.CreateClient<AssetLocationQueryClient>(companyid, LoginSession.SessionID);
                AssetTripInfo[] trips = client.GetAssetTripLins(companyid, long.Parse(ps[0]), dtFrom, dtTo);
                trips = trips.Where(m => m.TripOn != null || m.TripOff != null).ToArray();

                List<AssetTripItem> ls = new List<AssetTripItem>();
                TripColor[] colors = Enum.GetValues(typeof(TripColor)) as TripColor[];
                Random random = new Random();
                foreach (AssetTripInfo trip in trips)
                {
                    AssetTripItem item = new AssetTripItem();
                    Helper.CloneProperty(item, trip);

                    TripColor color = colors[random.Next(0, colors.Length)];
                    item.Color = color;

                    ls.Add(item);
                }
                return ls.ToArray();
            }
            else
            {
                return new AssetTripItem[0];
            }
        }

        private Tuple<string, string> GetLocationPrimaryDataSource()
        {
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                string[] ps = p.Split(';');
                string companyid = ps[1].Trim();//companyid
                if (string.IsNullOrEmpty(companyid))
                    companyid = SystemParams.CompanyID;

                var client = FleetServiceClientHelper.CreateClient<AssetLocationQueryClient>(companyid, LoginSession.SessionID);
                Tuple<string, string> datasource = client.GetLocationPrimaryDataSource(companyid, long.Parse(ps[0]));

                return datasource;
            }
            else
            {
                return new Tuple<string, string>(string.Empty, string.Empty);
            }
        }

        private JobSiteViewItem[] GetJobSites()
        {
            JobSiteViewItem[] items = null;
            if (LoginSession != null)
            {
                var clientdata = Context.Request.Params["ClientData"];

                GetJobsiteParameterItem p = JsonConvert.DeserializeObject<GetJobsiteParameterItem>(clientdata);
                p.SearchText = HttpUtility.HtmlDecode(p.SearchText);

                List<JobSiteViewItem> temp = new List<JobSiteViewItem>();
                if (!SystemParams.IsDealer)
                    items = AssetMapViewManagement.GetJobsites(LoginSession.SessionID, p.ContractorID, LoginSession.User.UID, p.SearchText);
                else
                    items = AssetMapViewManagement.GetDealerJobsites(LoginSession.SessionID, p.ContractorID, LoginSession.User.UID, p.SearchText);
                temp.AddRange(items);

                JobSiteViewItem js = new JobSiteViewItem() { ID = -1, Name = SystemParams.GetTextByKey(GetLanguageCookie(), "P_MV_NOJOBSITEASSIGNED", "No Jobsite Assigned") };
                temp.Add(js);
                items = temp.ToArray();
            }
            else
            {
                items = new JobSiteViewItem[0];
            }
            return items;
        }

        private CompanyLocationViewItem[] GetCompanyLocations()
        {
            CompanyLocationViewItem[] items = null;
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                string companyid = p;
                if (string.IsNullOrEmpty(companyid))
                    companyid = SystemParams.CompanyID;

                List<CompanyLocationViewItem> temps = new List<CompanyLocationViewItem>();
                if (!SystemParams.IsDealer)
                    items = AssetMapViewManagement.GetLocations(LoginSession.SessionID, companyid);
                else
                    items = AssetMapViewManagement.GetDealerLocations(LoginSession.SessionID, companyid);
            }
            else
            {
                items = new CompanyLocationViewItem[0];
            }
            return items.ToArray();
        }

        private MapAlertViewDefinitionItem[] GetMapAlertLayers()
        {
            MapAlertViewDefinitionItem[] items = null;
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                p = HttpUtility.HtmlDecode(p);
                int index = p.IndexOf(";");
                string companyid = p.Substring(0, index);
                string selectedViewID = p.Substring(index + 1);

                if (!SystemParams.IsDealer)
                    items = AssetMapViewManagement.GetMapAlertViews(LoginSession.SessionID, companyid, selectedViewID);
                else
                    items = AssetMapViewManagement.GetDealerMapAlertViews(LoginSession.SessionID, companyid, selectedViewID);
            }
            else
            {
                items = new MapAlertViewDefinitionItem[0];
            }
            return items;
        }

        private UserParamInfo GetUserParams()
        {
            UserParamInfo up = new UserParamInfo();
            up.AutoRecenterMap = true;
            if (LoginSession != null)
            {
                up = UserParams.GetUserParams(LoginSession.SessionID, LoginSession.User.UID);
            }
            return up;
        }

        private string SetUserParams()
        {
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];

                UserParamInfo up = JsonConvert.DeserializeObject<UserParamInfo>(p);
                UserParams.SetUserParams(LoginSession.User.UID, up);
            }
            return "OK";
        }

        private object SaveMapViewSearch()
        {
            if (LoginSession != null)
            {
                string data = Context.Request.Params["ClientData"];

                MapViewSearchItem item = JsonConvert.DeserializeObject<MapViewSearchItem>(data);
                return UserParams.SaveMapViewSearch(LoginSession.SessionID, LoginSession.User.UID, item);
            }

            return new MapViewSearchItem[0];
        }

        private object DeleteMapViewSearch()
        {
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                p = HttpUtility.HtmlDecode(p);

                return UserParams.DeleteMapViewSearch(LoginSession.SessionID, LoginSession.User.UID, p);
            }
            return new MapViewSearchItem[0];
        }

        private object GetAssetMapAttachments()
        {
            if (LoginSession != null)
            {
                var clientdata = Context.Request.Params["ClientData"];
                string[] ps = JsonConvert.DeserializeObject<string[]>(clientdata);
                string companyid = ps[0];
                if (string.IsNullOrEmpty(companyid))
                    companyid = SystemParams.CompanyID;
                long assetid = 0;
                if (!long.TryParse(ps[1], out assetid))
                    return null;

                var client = FleetServiceClientHelper.CreateClient<MapViewQueryClient>(companyid, LoginSession.SessionID);
                return client.GetAssetDocumentsOnMap(companyid, assetid);
            }
            return null;
        }

        private object RequestVideo()
        {
            if (LoginSession != null && SystemParams.HasLicense("SmartWitness"))
            {
                string p = Context.Request.Params["ClientData"];
                string[] ps = JsonConvert.DeserializeObject<string[]>(p);
                string companyid = ps[0];
                if (string.IsNullOrEmpty(companyid))
                    companyid = SystemParams.CompanyID;
                long aid = 0;
                DateTime dt = DateTime.MinValue;
                if (long.TryParse(ps[1], out aid))
                {
                    bool isCustomerTime = ps[2] == "1";
                    if (DateTime.TryParse(ps[3], out dt))
                    {
                        var cust = SystemParams.GetCustomerDetail(companyid);
                        dt = cust.CustomerTimeToUtc(dt);
                    }
                    int seconds = ps[4] == "1" ? 30 : 120;

                    long logid = 0;
                    if (!long.TryParse(ps[5], out logid))
                        logid = -1;
                    string src = ps[6];
                    string subsrc = ps[7];
                    string et = ps[8];
                    string msguid = ps[9];

                    var client = FleetServiceClientHelper.CreateClient<MapViewQueryClient>(companyid, LoginSession.SessionID);
                    var result = client.SendSmartWitnessVideoRequestWithTime(companyid, LoginSession.User.UID, aid, isCustomerTime, dt, seconds, logid, src, subsrc, et, msguid);
                    //var result = client.SendSmartWitnessVideoRequest(companyid, logid, LoginSession.User.UID);
                    return string.IsNullOrEmpty(result) ? "OK" : result;
                }
            }
            return "OK";
        }

        #region Send Location
        private UserInfo[] GetContacts()
        {
            UserInfo[] users;
            if (LoginSession != null)
            {
                users = UserManagement.GetUsers().Where(u => u.Active).ToArray();
            }
            else
            {
                users = new UserInfo[0];
            }
            return users;
        }
        private UserInfo[] GetMachineContacts()
        {
            UserInfo[] items = null;
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                p = HttpUtility.HtmlDecode(p);
                int index = p.IndexOf(";");
                string contractorid = p.Substring(0, index);
                string assetid = p.Substring(index + 1);

                items = UserManagement.GetUsersByAssetID(LoginSession.SessionID, Convert.ToInt64(assetid), contractorid);
            }
            else
            {
                items = new UserInfo[0];
            }
            return items;
        }
        private UserInfo[] GetJobsiteContacts()
        {
            UserInfo[] items = null;
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                p = HttpUtility.HtmlDecode(p);
                int index = p.IndexOf(";");
                string contractorid = p.Substring(0, index);
                string jsid = p.Substring(index + 1);

                items = UserManagement.GetUsersByJobsiteID(LoginSession.SessionID, Convert.ToInt64(jsid), contractorid);
            }
            else
            {
                items = new UserInfo[0];
            }
            return items;
        }
        private string SendEmails()
        {
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                p = HttpUtility.HtmlDecode(p);

                SendEmailsInfo si = JsonConvert.DeserializeObject<SendEmailsInfo>(p);
                if (string.IsNullOrEmpty(si.CompanyID))
                    si.CompanyID = SystemParams.CompanyID;

                if (si.Type == 0)
                {//SendLocation
                    AssetDetailViewItem asset = AssetMapViewManagement.GetAssetDetailItem(LoginSession.SessionID, si.CompanyID, si.ObjectID);
                    SendAssetLocation(asset, si);
                }
                else if (si.Type == 1)
                {//Send Jobsite
                    JobSiteItem jobsite = FleetServiceClientHelper.CreateClient<JobSiteProvider>().GetJobSiteItem(si.CompanyID, si.ObjectID);
                    SendJobsite(jobsite, si);
                }
                else if (si.Type == 3)
                {
                    // Send Route
                    SendRoute(si);
                }
            }
            return "OK";
        }


        private void SendAssetLocation(AssetDetailViewItem asset, SendEmailsInfo si)
        {
            StringKeyValue[] emailaddress = si.EmailAddress;
            StringKeyValue[] textaddress = si.TextAddress;
            var alllangs = GetUserLanguages(emailaddress, textaddress);
            var useriid = LoginSession.User.UID;
            var client = FleetServiceClientHelper.CreateClient<AttachmentClient>();
            if (emailaddress != null && emailaddress.Length > 0)
            {
                foreach (var item in emailaddress)
                {
                    string lang = GetUserLanguage(alllangs, item.Key);
                    string Subject = SystemParams.GetTextByKey(lang, "P_MV_LOCATIONOFASSET_COLON", "Location of Asset:") + " " + asset.Name2 + " " + asset.Name + " " + asset.Make + " " + asset.Model + " " + asset.VIN + " " + (asset.MakeYear > 0 ? asset.MakeYear.ToString() : "");

                    string Body = OrdinaryEmailFormat(lang, asset, si.Description, LoginSession.User.Name);
                    client.SendAssetLoationEmail(si.CompanyID, si.ObjectID, Subject, Body, new string[] { item.Value }, useriid);
                }
            }
            if (textaddress != null && textaddress.Length > 0)
            {
                foreach (var item in textaddress)
                {
                    string lang = GetUserLanguage(alllangs, item.Key);
                    string Body = OrdinaryTextFormat(lang, asset, si.Description, LoginSession.User.Name);
                    string Subject = "";//短信暂时不发Subject 8897反馈
                    client.SendAssetLoationText(si.CompanyID, si.ObjectID, Subject, Body, new string[] { item.Value }, useriid);
                }
            }
        }

        private string OrdinaryEmailFormat(string lang, AssetDetailViewItem asset, string desc, string username)
        {
            string EmailFormat = SystemParams.GetTextByKey(lang, "P_MV_LOCATIONOFASSET_COLON", "Location of Asset:") + "&nbsp;{0}&nbsp;{1}&nbsp;{2}&nbsp;{3}&nbsp;{4}&nbsp;{5}<br/><br/>";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_MV_DESCRIPTION_COLON", "Description:") + "<br/>";
            EmailFormat += "{6}<br/><br/>";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_MV_CLICKTHELINKBELOWTOVIEWDIRECTIONSTOTHISASSET", "Click the link below to view directions to this asset:") + "<br/>";
            EmailFormat += "<a href=\"{7}\">" + SystemParams.GetTextByKey(lang, "P_MV_VIEWDIRECTIONS", "View Directions") + "</a>";

            if (asset.Location == null)
                asset.Location = new LocationViewItem();

            if (!string.IsNullOrEmpty(desc))
            {
                desc = Regex.Replace(desc, "\\[site name\\]", SystemParams.CustomerDetail.Name, RegexOptions.IgnoreCase);
                desc = Regex.Replace(desc, "\\[User Name\\]", username, RegexOptions.IgnoreCase);
                desc = Regex.Replace(desc, "\\[asset name\\]", asset.DisplayName, RegexOptions.IgnoreCase);
            }

            return string.Format(EmailFormat,
               HttpUtility.HtmlEncode(asset.Name2),
               HttpUtility.HtmlEncode(asset.Name),
               HttpUtility.HtmlEncode(asset.Make),
               HttpUtility.HtmlEncode(asset.Model),
               HttpUtility.HtmlEncode(asset.VIN),
               HttpUtility.HtmlEncode(asset.MakeYear > 0 ? asset.MakeYear.ToString() : ""),
               HttpUtility.HtmlEncode(desc ?? "").Replace("\n", "<br>"),
                "https://www.google.com/maps/dir/?api=1&destination=" + asset.Location.Latitude + "," + asset.Location.Longitude + "&travelmode=driving");
        }

        private string OrdinaryTextFormat(string lang, AssetDetailViewItem asset, string desc, string username)
        {
            //string EmailFormat = SystemParams.GetTextByKey(lang, "P_MV_LOCATIONOFASSET_COLON", "Location of Asset:") + " {0}. ";
            ////string EmailFormat = "Location of Asset: {0} {1} {2} {3} {4} {5}. ";
            ////EmailFormat += "Description: ";
            ////EmailFormat += "{6}. ";
            //EmailFormat += "<a href=\"{1}\">" + SystemParams.GetTextByKey(lang, "P_MV_VIEWDIRECTIONS", "View Directions") + "</a>";
            //if (asset.Location == null)
            //    asset.Location = new LocationViewItem();
            //return string.Format(EmailFormat,
            //   HttpUtility.HtmlEncode(asset.DisplayName),
            //    //HttpUtility.HtmlEncode(asset.Name),
            //    //HttpUtility.HtmlEncode(asset.Make),
            //    //HttpUtility.HtmlEncode(asset.Model),
            //    //HttpUtility.HtmlEncode(asset.VIN),
            //    //HttpUtility.HtmlEncode(asset.MakeYear > 0 ? asset.MakeYear.ToString() : ""),
            //    //HttpUtility.HtmlEncode(desc ?? ""),
            //    "https://www.google.com/maps/dir/?api=1&destination=" + asset.Location.Latitude + "," + asset.Location.Longitude /*+ "&travelmode=driving"*/);

            if (!string.IsNullOrEmpty(desc))
            {
                desc = Regex.Replace(desc, "\\[site name\\]", SystemParams.CustomerDetail.Name, RegexOptions.IgnoreCase);
                desc = Regex.Replace(desc, "\\[User Name\\]", username, RegexOptions.IgnoreCase);
                desc = Regex.Replace(desc, "\\[asset name\\]", asset.DisplayName, RegexOptions.IgnoreCase);
            }
            return desc + Environment.NewLine + Environment.NewLine + "https://www.google.com/maps/dir/?api=1&destination=" + asset.Location.Latitude + "," + asset.Location.Longitude;
        }

        private void SendJobsite(JobSiteItem jobsite, SendEmailsInfo si)
        {
            StringKeyValue[] emailaddress = si.EmailAddress;
            StringKeyValue[] textaddress = si.TextAddress;
            var alllangs = GetUserLanguages(emailaddress, textaddress);
            string Subject = jobsite.Name;
            if (!string.IsNullOrEmpty(jobsite.Code))
                Subject += "/" + jobsite.Code;
            if (!string.IsNullOrEmpty(jobsite.Number))
                Subject += "/" + jobsite.Number;

            var useriid = LoginSession.User.UID;

            if (emailaddress != null && emailaddress.Length > 0)
            {
                foreach (var item in emailaddress)
                {
                    string lang = GetUserLanguage(alllangs, item.Key);
                    string Body = OrdinaryJobsiteEmailFormat(lang, jobsite, si.Description, LoginSession.User.Name);
                    FleetServiceClientHelper.CreateClient<AttachmentClient>().SendAssetLoationEmail(si.CompanyID, si.ObjectID, Subject, Body, new string[] { item.Value }, useriid);
                }
            }

            if (textaddress != null && textaddress.Length > 0)
            {
                foreach (var item in textaddress)
                {
                    string lang = GetUserLanguage(alllangs, item.Key);
                    string Body = OrdinaryJobsiteTextFormat(lang, jobsite, si.Description, LoginSession.User.Name);
                    FleetServiceClientHelper.CreateClient<AttachmentClient>().SendAssetLoationText(si.CompanyID, si.ObjectID, Subject, Body, new string[] { item.Value }, useriid);
                }
            }
        }

        private void SendRoute(SendEmailsInfo si)
        {
            var emailaddress = si.EmailAddress;
            var subject = si.Title;

            var useriid = LoginSession.User.UID;
            if (emailaddress != null && emailaddress.Length > 0)
            {
                var body = @"<!doctype html>
<html lang=""en""><head><style type=""text/css"">
.fa {
    display: none;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: inherit;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
.routeSummary {
    line-height: 30px;
    padding: 0 20px 10px 20px;
    border-bottom: 1px solid #ccc;
    margin-bottom: 20px;
}
.routeSummary > .routeSummaryTitle {
    font-size: 1.6em;
    font-weight: 500;
}
.routeSummary > .routeSummaryDetail {
    font-size: 1.2em;
    color: gray;
}
.routeSummary .fa-car {
    font-size: 1.2em;
    padding-right: 6px;
    font-weight: bold;
}
.routeSummary .fa-car::before { content: '\f1b9'; }
.routeSummary .routeSummaryDistance { margin-left: 10px; }
.routeFeature {
    line-height: 30px;
    padding: 0 20px 0 40px;
    position: relative;
}
.routeFeature > .fa {
    position: absolute;
    width: 24px;
    height: 24px;
    left: 10px;
    top: 3px;
    line-height: 24px;
    text-align: center;
    font-size: 1.3em;
}
.routeFeature > .fa::before { content: '\f054'; }
.routeFeature > .fa-ship::before { content: '\f21a'; }
.routeFeature > .fa-merge-right { transform: scaleX(-1); }
.routeFeature > .fa-merge-right::before,
.routeFeature > .fa-merge::before { content: '\f387'; }
.routeFeature > .fa-up::before { content: '\f176'; }
.routeFeature > .fa-left::before,
.routeFeature > .fa-right::before { content: '\f148'; }
.routeFeature > .fa-back::before { content: '\f175'; }
.routeFeature > .fa-left { transform: rotate(-90deg); }
.routeFeature > .fa-right { transform: scaleX(-1) rotate(-90deg); }
.routeFeature > .fa-back { transform: rotate(180deg); }
.routeFeature > .routeFeatureMessage { font-size: 1.2em; }
.routeFeature > .routeFeatureDetail {
    color: #aaa;
    position: relative;
    height: 30px;
    font-size: 0.9em;
}
.routeFeature > .routeFeatureDetail > .routeFeatureDetailBorder {
    border-bottom: 1px solid #ccc;
    position: absolute;
    width: 100%;
    top: 50%;
}
.routeFeature > .routeFeatureDetail > span {
    background-color: white;
    position: absolute;
    padding-right: 10px;
}
</style></head><body>";
                body += "<p>" + (si.Description ?? "").Replace("\n", "<br>") + "</p>";
                body += si.HtmlBody + "</body></html>";
                string[] address = emailaddress.Select(m => m.Value).ToArray();
                FleetServiceClientHelper.CreateClient<AttachmentClient>().SendRoutesEmail(si.CompanyID, subject, body, address, useriid);
            }
        }

        private string OrdinaryJobsiteEmailFormat(string lang, JobSiteItem jobsite, string desc, string username)
        {
            string EmailFormat = "{7}";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_MV_LATLONG_COLON", "Lat/Long:") + " {0},{1}<br/>";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_MV_DELIVERYADDRESS_COLON", "Delivery Address:") + " {2}<br/<br/>";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_JS_FOREMAN_COLON", "Foreman:") + " {3}<br/><br/>";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_JS_STATDATE_COLON", "Start Date:") + " {4}<br/>";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_JS_ENDDATE_COLON", "End Date:") + " {5}<br/><br/>";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_MA_NOTES_COLON", "Notes:") + " {6}<br/>";

            if (!string.IsNullOrEmpty(desc))
            {
                desc = Regex.Replace(desc, "\\[site name\\]", SystemParams.CustomerDetail.Name, RegexOptions.IgnoreCase);
                desc = Regex.Replace(desc, "\\[User Name\\]", username, RegexOptions.IgnoreCase);
                desc = Regex.Replace(desc, "\\[jobsite\\]", jobsite.Name, RegexOptions.IgnoreCase);
                desc = HttpUtility.HtmlEncode(desc);
            }

            return string.Format(EmailFormat,
               HttpUtility.HtmlEncode(jobsite.Latitude),
               HttpUtility.HtmlEncode(jobsite.Longitude),
               HttpUtility.HtmlEncode(jobsite.Address1),
               HttpUtility.HtmlEncode(jobsite.Foreman),
               HttpUtility.HtmlEncode(jobsite.StartDate == null ? "" : jobsite.StartDate.Value.ToShortDateString()),
               HttpUtility.HtmlEncode(jobsite.EndDate == null ? "" : jobsite.EndDate.Value.ToShortDateString()),
               HttpUtility.HtmlEncode(jobsite.Notes ?? "").Replace("\n", "<br/>"),
               string.IsNullOrWhiteSpace(desc) ? "" : desc.Replace("\n", "<br/>") + "<br/><br/>");
        }

        private string OrdinaryJobsiteTextFormat(string lang, JobSiteItem jobsite, string desc, string username)
        {
            string EmailFormat = "{7}";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_MV_LATLONG_COLON", "Lat/Long:") + " {0},{1}  ";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_MV_DELIVERYADDRESS_COLON", "Delivery Address:") + " {2}  ";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_JS_FOREMAN_COLON", "Foreman:") + " {3}  ";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_JS_STATDATE_COLON", "Start Date:") + " {4}  ";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_JS_ENDDATE_COLON", "End Date:") + " {5}  ";
            EmailFormat += SystemParams.GetTextByKey(lang, "P_MA_NOTES_COLON", "Notes:") + " {6}";

            if (!string.IsNullOrEmpty(desc))
            {
                desc = Regex.Replace(desc, "\\[site name\\]", SystemParams.CustomerDetail.Name, RegexOptions.IgnoreCase);
                desc = Regex.Replace(desc, "\\[User Name\\]", username, RegexOptions.IgnoreCase);
                desc = Regex.Replace(desc, "\\[jobsite\\]", jobsite.Name, RegexOptions.IgnoreCase);
            }

            return string.Format(EmailFormat, jobsite.Latitude,
               jobsite.Longitude,
               jobsite.Address1,
               jobsite.Foreman,
               jobsite.StartDate == null ? "" : jobsite.StartDate.Value.ToShortDateString(),
               jobsite.EndDate == null ? "" : jobsite.EndDate.Value.ToShortDateString(),
               jobsite.Notes ?? "",
               string.IsNullOrWhiteSpace(desc) ? "" : desc + "\r\n\r\n");
        }

        public static Foresight.Standard.StringKeyValue[] GetUserLanguages(StringKeyValue[] emailaddress, StringKeyValue[] textaddress)
        {
            List<string> uids = new List<string>();
            if (emailaddress != null && emailaddress.Length > 0)
            {
                List<string> ids = emailaddress.Where(m => !string.IsNullOrEmpty(m.Key)).Select(m => m.Key).ToList();
                if (ids != null && ids.Count > 0)
                    uids.AddRange(ids);
            }

            if (textaddress != null && textaddress.Length > 0)
            {
                List<string> ids = textaddress.Where(m => !string.IsNullOrEmpty(m.Key)).Select(m => m.Key).ToList();
                if (ids != null && ids.Count > 0)
                    uids.AddRange(ids);
            }

            Foresight.Standard.StringKeyValue[] alllangs = null;
            if (uids.Count > 0)
            {
                alllangs = FleetServiceClientHelper.CreateClient<Foresight.Fleet.Services.User.UserQueryClient>().GetUserLanguages();
            }
            return alllangs;
        }

        public static string GetUserLanguage(Foresight.Standard.StringKeyValue[] alllangs, string uid)
        {
            var lang = "en-us";
            if (alllangs != null)
            {
                var item = alllangs.FirstOrDefault(m => m.Key == uid);
                if (item != null)
                    lang = item.Value;
            }
            return lang;
        }

        private string GetShotLink(string longurl)
        {
            string serverurl = "https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=AIzaSyBzQFCgFK-ytQGGfMKePtvMyb1kSqvJ7_E";

            string result = longurl;
            try
            {
                //string dl = string.Format("https://foresight.page.link/?link={0}", longurl);
                var obj = new
                {
                    dynamicLinkInfo = new
                    {
                        domainUriPrefix = "https://foresight.page.link",
                        link = longurl
                    },
                    suffix = new
                    {
                        option = "SHORT"
                    }
                };
                string json = JsonConvert.SerializeObject(obj);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serverurl);
                request.Method = "POST";
                request.Accept = "application/json";
                //request.Accept = "*/*";
                request.ContentType = "application/json";

                byte[] byteRequest = Encoding.Default.GetBytes(json);
                using (Stream rs = request.GetRequestStream())
                {
                    rs.Write(byteRequest, 0, byteRequest.Length);
                    //rs.Close();
                }
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    Stream resultStream = response.GetResponseStream();
                    StreamReader sr = new StreamReader(resultStream, Encoding.UTF8);
                    string rjson = sr.ReadToEnd();
                    Newtonsoft.Json.Linq.JObject robj = JsonConvert.DeserializeObject(rjson) as Newtonsoft.Json.Linq.JObject;

                    if (robj != null)
                    {
                        result = robj["shortLink"].ToString();
                    }

                    sr.Close();
                    resultStream.Close();
                    response.Close();
                }
            }
            catch (Exception ex)
            {
                SystemParams.WriteLog("error", "GetShotLink", ex.Message, ex.ToString());
            }

            return result;
        }

        #endregion

        #region Shape File
        private object GetShapeFileInfos()
        {
            try
            {
                if (LoginSession != null)
                {
                    string clientdata = HttpUtility.HtmlDecode(Context.Request.Params["ClientData"]);
                    StringKeyValue kv = JsonConvert.DeserializeObject<StringKeyValue>(clientdata);
                    string customerid = kv.Key;

                    ShapeFileItem[] files = null;
                    if (!SystemParams.IsDealer)
                        files = AssetMapViewManagement.GetShapes(LoginSession.SessionID, customerid, kv.Value);
                    else
                        files = AssetMapViewManagement.GetDealerShapes(LoginSession.SessionID, customerid, kv.Value);

                    return files.OrderBy(m => m.Name).ToArray();
                }
                else
                {
                    return new ShapeFileItem[0];
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private object ImportShape()
        {
            try
            {
                if (LoginSession != null)
                {
                    string clientdata = HttpUtility.HtmlDecode(Context.Request.Params["ClientData"]);
                    StringKeyValue kv = JsonConvert.DeserializeObject<StringKeyValue>(clientdata);
                    string customerid = kv.Key;
                    if (string.IsNullOrEmpty(customerid))
                        customerid = SystemParams.CompanyID;

                    HttpPostedFile uploadFile = null;
                    byte[] iconfilebyte = null;
                    string filename = "";
                    if (Context.Request.Files.Count > 0)
                    {
                        uploadFile = Context.Request.Files[0];
                        iconfilebyte = ConvertFile2bytes(uploadFile);
                        filename = uploadFile.FileName;
                    }

                    FleetServiceClientHelper.CreateClient<ShapeFileProvider>(customerid, LoginSession.SessionID).ImportShape(customerid, kv.Value, kv.Tag1, LoginSession.User.UID, filename, iconfilebyte);

                    return "OK";
                }
                return "Failed";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private object GetShapeData()
        {
            try
            {
                if (GetCurrentLoginSession() != null)
                {
                    string clientdata = HttpUtility.HtmlDecode(Context.Request.Params["ClientData"]);
                    StringKeyValue kv = JsonConvert.DeserializeObject<StringKeyValue>(clientdata);
                    string customerid = kv.Key;
                    if (string.IsNullOrEmpty(customerid))
                        customerid = SystemParams.CompanyID;
                    string fileName = kv.Tag1 ?? "";

                    byte[] buffer = FleetServiceClientHelper.CreateClient<ShapeFileProvider>(customerid, LoginSession.SessionID).GetShapeData(customerid, Convert.ToInt64(kv.Value));
                    Shape.Shape shape = new Shape.Shape();

                    if (fileName == "" || fileName.EndsWith(".shp", StringComparison.OrdinalIgnoreCase))
                        Shape.ShapeFileParser.ParseFromShapeFile(buffer, shape);
                    else if (fileName.EndsWith(".kml", StringComparison.OrdinalIgnoreCase))
                        Shape.ShapeFileParser.ParseFromKMLFile(buffer, shape);
                    else if (fileName.EndsWith(".kmz", StringComparison.OrdinalIgnoreCase))
                        Shape.ShapeFileParser.ParseFromKMZFile(buffer, shape);

                    Shape.SimpleShape ss = new Shape.SimpleShape();
                    ss.FromShapeObj(shape);
                    //#if DEBUG
                    //                    if (Convert.ToInt64(kv.Value) == 12d)
                    //                        ss = AutoJobsitesCreator.DoTest(GetCurrentLoginSession().SessionID);
                    //#endif
                    return ss;
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private object UpdateShapeName()
        {
            try
            {
                if (LoginSession != null)
                {
                    var clientdata = Context.Request.Form["ClientData"].Split((char)170);
                    var customerid = HttpUtility.HtmlDecode(clientdata[0]);
                    var data = HttpUtility.HtmlDecode(clientdata[1]);
                    ShapeFileItem shape = JsonConvert.DeserializeObject<ShapeFileItem>(data);
                    if (string.IsNullOrEmpty(customerid))
                        customerid = SystemParams.CompanyID;

                    FleetServiceClientHelper.CreateClient<ShapeFileProvider>(customerid, LoginSession.SessionID).UpdateShapeName(customerid, shape.ID, shape.Name, shape.Notes);

                    return "OK";
                }
                return "Failed";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

        }

        private object DeleteShape()
        {
            try
            {
                if (LoginSession != null)
                {
                    string clientdata = HttpUtility.HtmlDecode(Context.Request.Params["ClientData"]);
                    StringKeyValue kv = JsonConvert.DeserializeObject<StringKeyValue>(clientdata);
                    string customerid = kv.Key;
                    if (string.IsNullOrEmpty(customerid))
                        customerid = SystemParams.CompanyID;

                    FleetServiceClientHelper.CreateClient<ShapeFileProvider>(customerid, LoginSession.SessionID).DeleteShape(customerid, Convert.ToInt64(kv.Value), LoginSession.User.UID);

                    return "OK";
                }
                return "Failed";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private byte[] ConvertFile2bytes(HttpPostedFile uploadFile)
        {
            byte[] dataBuffer = new byte[uploadFile.InputStream.Length];
            uploadFile.InputStream.Position = 0;
            uploadFile.InputStream.Read(dataBuffer, 0, dataBuffer.Length);
            uploadFile.InputStream.Close();
            return dataBuffer;
        }

        #endregion


        private string GetNowFormatDate()
        {
            if (LoginSession != null)
            {
                return SystemParams.ConvertToUserTimeFromUtc(LoginSession.User, DateTime.UtcNow).ToString("M/d/yyyy h:m:s tt");
            }
            return "";
        }

        public class SendEmailsInfo
        {
            public int Type { get; set; }
            public string CompanyID { get; set; }
            public long ObjectID { get; set; }
            public long[] ObjectIDs { get; set; }
            public string Description { get; set; }
            public StringKeyValue[] EmailAddress { get; set; }
            public StringKeyValue[] TextAddress { get; set; }
            public string HtmlBody { get; set; }
            public string Title { get; set; }
            public string AssignTo { get; set; }
        }

        public class GetMachineParameterItem
        {
            public bool IsAutoRefresh { get; set; }
            public string ViewID { get; set; }
            public string ContractorID { get; set; }
            public int Onroad { get; set; }
            public string SearchText { get; set; }
            public MapAlertLayerDefinitionItem[] Layers { get; set; }
            public string MachineIDs { get; set; }
            public bool ExcludeNoLocation { get; set; }
            public int Attachment { get; set; }
        }

        public class GetJobsiteParameterItem
        {
            public bool IsAutoRefresh { get; set; }
            public string ContractorID { get; set; }
            public int Onroad { get; set; }
            public string SearchText { get; set; }
        }

        public class AssetTripItem : AssetTripInfo
        {
            public TripColor Color { get; set; }
            public string TripTimeStr { get { return TripTime == null ? "" : TripTime.Value.ToString(); } }
            public string TripOnLocalAsofTimeStr { get { return TripOn == null ? "" : TripOn.LocalAsofTime.ToString("MM/dd/yyyy hh:mm:ss tt"); } }
            public string TripOffLocalAsofTimeStr { get { return TripOff == null ? "" : TripOff.LocalAsofTime.ToString("MM/dd/yyyy hh:mm:ss tt"); } }
            public string TripOnAddress
            {
                get
                {
                    var address = "";
                    if (TripOn != null)
                    {
                        if (!string.IsNullOrEmpty(TripOn.Street))
                            address = TripOn.Street;
                        if (!string.IsNullOrEmpty(TripOn.City))
                            address += ", " + TripOn.City;
                        if (!string.IsNullOrEmpty(TripOn.State))
                            address += ", " + TripOn.State;
                    }
                    return address;
                }
            }
            public string TripOffAddress
            {
                get
                {
                    var address = "";
                    if (TripOff != null)
                    {
                        if (!string.IsNullOrEmpty(TripOff.Street))
                            address = TripOff.Street;
                        if (!string.IsNullOrEmpty(TripOff.City))
                            address += ", " + TripOff.City;
                        if (!string.IsNullOrEmpty(TripOff.State))
                            address += ", " + TripOff.State;
                    }
                    return address;
                }
            }
        }

        public enum TripColor
        {
            Blue,
            Green,
            Purple,
            Yellow,
            Pink,
            Red,
        }
    }
}