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.Site;
using IronIntel.Contractor.MapView;
using IronIntel.Contractor.Users;
using Foresight.ServiceModel;
using IronIntel.Contractor.Contact;
using Foresight.Fleet.Services.Attachment;
using Foresight.Fleet.Services.JobSite;
using Foresight.Fleet.Services.MapView;

namespace IronIntel.Contractor.Site.MapView
{
    public class MapViewHandler : IronIntelHttpHandlerBase
    {
        public override string GetIronSystemServiceAddress()
        {
            return SystemParams.SystemServiceAddresses[0];
        }

        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 "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 "GetMachineContacts":
                        result = GetMachineContacts();
                        break;
                    case "SendLocation":
                        result = SendLocation();
                        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;
                    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.Write(json);
            Context.Response.End();
        }

        private string GetServerVersion()
        {
            string serverVersion = SystemParams.GetVersion();
            return serverVersion;
        }
        private AssetViewItem[] GetAssets()
        {
            AssetViewItem[] 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);
                }

                assets = AssetMapViewManagement.GetAssets(LoginSession.SessionID, p.ContractorID, LoginSession.User.UID, p.SearchText, p.Onroad, viewqueryparam, !p.ExcludeNoLocation);
                SystemParams.WriteRefreshLog(LoginSession.User.UID, UserHostAddress, "Assets", p.IsAutoRefresh ? "Auto" : "Manual");
            }
            else
                assets = new AssetViewItem[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>();
                groups = AssetMapViewManagement.GetAssetGroups(LoginSession.SessionID, companyid, LoginSession.User.UID, p.SearchText);
                temp.AddRange(groups);

                AssetGroupViewItem eg = new AssetGroupViewItem() { ID = "-1", Name = "No Asset Group Assigned" };
                //eg.Assets = AssetMapViewManagement.GetNoGroupAssets(companyid);
                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 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);

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

                items = AssetMapViewManagement.GetJobsites(LoginSession.SessionID, companyid, LoginSession.User.UID, p.SearchText);


                List<JobSiteViewItem> temp = new List<JobSiteViewItem>();
                items = AssetMapViewManagement.GetJobsites(LoginSession.SessionID, companyid, LoginSession.User.UID, p.SearchText);
                temp.AddRange(items);

                JobSiteViewItem js = new JobSiteViewItem() { ID = -1, Name = "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;

                var client = FleetServiceClientHelper.CreateClient<MapViewQueryClient>(companyid, LoginSession.SessionID);
                CustomerLocation[] locs = client.GetContractorAndDealerLocations(companyid);
                List<CompanyLocationViewItem> temps = new List<CompanyLocationViewItem>();
                foreach (var loc in locs)
                {
                    CompanyLocationViewItem l = new CompanyLocationViewItem();
                    l.ID = loc.ID;
                    l.Latitude = loc.Latitude;
                    l.Longitude = loc.Longitude;
                    l.LocationName = loc.Name;
                    l.Notes = loc.Notes;
                    l.IconUrl = loc.IconUrl;
                    temps.Add(l);
                }
                items = temps.ToArray();

                //items = LocationManagement.GetCompanyLocations("");
            }
            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);

                items = AssetMapViewManagement.GetMapAlertViews(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];
        }

        #region Send Location
        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 string SendLocation()
        {
            if (LoginSession != null)
            {
                string p = Context.Request.Params["ClientData"];
                p = HttpUtility.HtmlDecode(p);

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

                AssetDetailViewItem asset = AssetMapViewManagement.GetAssetDetailItem(LoginSession.SessionID, si.CompanyID, si.AssetID);
                SendMail(asset, si);
            }
            return "OK";
        }

        private void SendMail(AssetDetailViewItem asset, SendLocationInfo si)
        {
            string[] emailaddress = si.EmailAddress;
            string[] textaddress = si.TextAddress;
            string Subject = "Location of Asset: " + asset.Name2 + " " + asset.Name + " " + asset.Make + " " + asset.Model + " " + asset.VIN + " " + (asset.MakeYear > 0 ? asset.MakeYear.ToString() : "");
            var useriid = LoginSession.User.UID;
            if (emailaddress != null && emailaddress.Length > 0)
            {
                string Body = OrdinaryEmailFormat(asset, si.Description);
                FleetServiceClientHelper.CreateClient<AttachmentClient>().SendAssetLoationEmail(si.CompanyID, si.AssetID, Subject, Body, emailaddress.ToArray(), useriid);
            }
            if (textaddress != null && textaddress.Length > 0)
            {
                string Body = OrdinaryTextFormat(asset, si.Description);
                Subject = "";//短信暂时不发Subject 8897反馈
                FleetServiceClientHelper.CreateClient<AttachmentClient>().SendAssetLoationEmail(si.CompanyID, si.AssetID, Subject, Body, textaddress.ToArray(), useriid);
            }
        }

        private string OrdinaryEmailFormat(AssetDetailViewItem asset, string desc)
        {
            string EmailFormat = "Location of Asset:&nbsp;{0}&nbsp;{1}&nbsp;{2}&nbsp;{3}&nbsp;{4}&nbsp;{5}</br></br>";
            EmailFormat += "Description:</br>";
            EmailFormat += "{6}</br><br/>";
            EmailFormat += "Click the link below to view directions to this asset:</br>";
            EmailFormat += "<a href=\"{7}\">{7}</a>";
            if (asset.Location == null)
                asset.Location = new LocationViewItem();
            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(AssetDetailViewItem asset, string desc)
        {
            string EmailFormat = "Location of Asset:&nbsp;{0}&nbsp;{1}&nbsp;{2}&nbsp;{3}&nbsp;{4}&nbsp;{5}</br></br>";
            EmailFormat += "Description:</br>";
            EmailFormat += "{6}</br><br/>";
            EmailFormat += "Click the link below to view directions to this asset:</br>";
            EmailFormat += "{7}";
            if (asset.Location == null)
                asset.Location = new LocationViewItem();
            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");
        }

        #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;
                    if (string.IsNullOrEmpty(customerid))
                        customerid = SystemParams.CompanyID;

                    ShapeFileInfo[] files = FleetServiceClientHelper.CreateClient<ShapeFileProvider>(customerid, LoginSession.SessionID).GetShapeFileInfos(customerid, kv.Value);
                    if (files == null || files.Length == 0)
                        return new ShapeFileItem[0];

                    List<ShapeFileItem> list = new List<ShapeFileItem>();
                    foreach (ShapeFileInfo fi in files)
                    {
                        ShapeFileItem item = new ShapeFileItem();
                        Helper.CloneProperty(item, fi);
                        list.Add(item);
                    }
                    return list.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;
                    if (Context.Request.Files.Count > 0)
                    {
                        uploadFile = Context.Request.Files[0];
                        iconfilebyte = ConvertFile2bytes(uploadFile);
                    }

                    FleetServiceClientHelper.CreateClient<ShapeFileProvider>(customerid, LoginSession.SessionID).ImportShape(customerid, kv.Value, kv.Tag1, LoginSession.User.UID, 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;

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

                    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

        public class SendLocationInfo
        {
            public string CompanyID { get; set; }
            public long AssetID { get; set; }
            public string Description { get; set; }
            public string[] EmailAddress { get; set; }
            public string[] TextAddress { 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 class GetJobsiteParameterItem
        {
            public bool IsAutoRefresh { get; set; }
            public string ContractorID { get; set; }
            public int Onroad { get; set; }
            public string SearchText { get; set; }
        }

        public class MachineQueryResult
        {
            public MachineViewItem[] Machines { get; set; }
            public AssetGroupViewItem[] Groups { get; set; }
        }
        public class MapViewSearchClient
        {
            public string SearchName { get; set; }
            public bool IsDefault { get; set; }
            public int Type { get; set; }
        }
    }
}