using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Web;
using Foresight.Data;
using Foresight.ServiceModel;
using IronIntel.Services.Business.Admin;
using IronIntel.Contractor.Machines;
using Foresight.Fleet.Services.Asset;
using Foresight.Fleet.Services.MapView;
using Foresight.Fleet.Services.JobSite;

namespace IronIntel.Contractor.MapView
{
    public class AssetMapViewManagement : MachineManagement
    {
        /// <summary>
        /// 根据Contractorid获取机器列表
        /// </summary>
        /// <returns></returns>
        public static AssetViewItem[] GetAssets(string sessionid, string companyid, string useriid, string filtertext, int onroad, MachineAlertViewQueryParameter param, bool IncludeNoLocation)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;

            MapViewAssetsQueryParam qp = new MapViewAssetsQueryParam();
            qp.FilterString = filtertext;
            qp.OnRoad = onroad;
            qp.IncludeNoLocation = IncludeNoLocation;
            qp.IncludeAssetGroups = true;
            qp.IncludeJobSites = true;
            if (param != null)
            {
                qp.ViewId = param.ViewID;
                qp.AlertViewQueryParam = param;
            }

            var client = FleetServiceClientHelper.CreateClient<MapViewQueryClient>(companyid, sessionid);
            AssetMapViewPinItem[] assets = client.GetAssets(companyid, useriid, qp);
            List<AssetViewItem> result = new List<AssetViewItem>();
            foreach (var a in assets)
            {
                AssetViewItem avi = new AssetViewItem();
                Helper.CloneProperty(avi, a);
                result.Add(avi);
            }
            return result.ToArray();
        }

        public static AssetDetailViewItem GetAssetDetailItem(string sessionid, string companyid, long machineid, string datasource = null)
        {
            var client = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid);
            var asset = client.GetAssetDetailInfo(companyid, machineid);
            AssetDetailViewItem mi = new AssetDetailViewItem();
            mi.ID = asset.ID;
            mi.Name = asset.Name;
            mi.Name2 = asset.Name2;
            mi.VIN = asset.VIN;
            mi.MakeYear = asset.MakeYear;
            mi.Make = asset.MakeName;
            mi.Model = asset.ModelName;
            mi.AssetType = asset.TypeName;
            mi.GroupNames = asset.GroupNames;
            mi.IconUrl = asset.MapViewIconUrl;
            mi.AssetIconUrl = asset.AssetIconUrl;

            if (asset.CurrentHours != null)
            {
                mi.EngineHours = asset.CurrentHours.Corrected;
                mi.EngineHoursDate = asset.CurrentHours.AsofTimeLocal;
            }

            mi.Location = new LocationViewItem();
            var loc = asset.CurrentLocation;
            if (!string.IsNullOrWhiteSpace(datasource)
                && (loc == null || string.Compare(datasource, loc.DataSource, true) != 0))
            {
                AssetLocationInfo[] locs = client.GetAssetCurrentLocation(companyid, machineid);
                var tempLoc = locs.FirstOrDefault(l => string.Compare(datasource, l.DataSource, true) != 0);
                if (tempLoc != null)
                {
                    mi.Location.Latitude = tempLoc.Latitude;
                    mi.Location.Longitude = tempLoc.Longitude;
                    mi.Location.LocationTime = tempLoc.AsofTimeLocal;
                    mi.Location.Speed = tempLoc.Speed;
                    mi.Location.SpeedUnit = tempLoc.SpeedUnits;
                    mi.Location.PostedSpeed = tempLoc.PostedSpeedLimit;
                    mi.Location.PostedSpeedUnit = tempLoc.SpeedLimitUnits;
                    mi.Location.Street = tempLoc.Street;
                }
            }
            else if (loc != null)
            {
                mi.Location.Latitude = loc.Latitude;
                mi.Location.Longitude = loc.Longitude;
                mi.Location.LocationTime = loc.AsofTimeLocal;
                mi.Location.Speed = loc.Speed;
                mi.Location.SpeedUnit = loc.SpeedUnits;
                mi.Location.PostedSpeed = loc.PostedSpeedLimit;
                mi.Location.PostedSpeedUnit = loc.SpeedLimitUnits;
                mi.Location.Street = loc.Street;
            }

            if (asset.CurrentOdometer != null)
            {
                mi.Odometer = asset.CurrentOdometer.Corrected;
                mi.OdometerUOM = asset.CurrentOdometer.UOM;
            }

            return mi;
        }

        public static AssetGroupViewItem[] GetAssetGroups(string sessionid, string companyid, string useriid, string searchtext)
        {
            var client = FleetServiceClientHelper.CreateClient<MapViewQueryClient>(companyid, sessionid);
            AssetGroupInfo[] gs = client.GetAvailableAssetGroups(companyid, useriid, searchtext, false);

            List<AssetGroupViewItem> list = new List<AssetGroupViewItem>();
            foreach (var g in gs)
            {
                AssetGroupViewItem ag = new AssetGroupViewItem();
                ag.ID = g.Id;
                ag.Name = g.Name;
                //ag.Assets = g.Assets;
                list.Add(ag);
            }
            return list.ToArray();
        }

        public static JobSiteViewItem[] GetJobsites(string sessionid, string companyid, string useriid, string searchtext)
        {
            var client = FleetServiceClientHelper.CreateClient<MapViewQueryClient>(companyid, sessionid);
            MapViewJobSiteInfo[] jss = client.GetAvailableJobSites(companyid, useriid, searchtext, false);

            List<JobSiteViewItem> list = new List<JobSiteViewItem>();
            foreach (var js in jss)
            {
                JobSiteViewItem ajs = new JobSiteViewItem();
                ajs.ID = js.ID;
                ajs.Name = js.Name;
                ajs.Latitude = js.Latitude;
                ajs.Longitude = js.Longitude;
                ajs.Radius = js.Radius;
                ajs.Radius_UOM = js.RadiusUOM;
                //ajs.Assets = js.Assets;

                System.Drawing.Color color = System.Drawing.Color.Orange;
                try
                {
                    color = System.Drawing.ColorTranslator.FromHtml(js.Color);
                }
                catch
                {
                }
                ajs.Color = new IIColor() { Alpha = color.A, Red = color.R, Green = color.G, Blue = color.B };
                if (js.Polygon != null)
                {
                    List<PostionItem> temp = new List<PostionItem>();
                    foreach (var p in js.Polygon)
                    {
                        temp.Add(new PostionItem(p.Latitude, p.Longtitude));
                    }
                    ajs.Polygon = temp.ToArray();
                }
                ajs.Notes = js.Notes;
                list.Add(ajs);
            }
            return list.ToArray();
        }

        private static Dictionary<string, List<MachineViewItem>> GetGroupAssets(string useriid, FISqlConnection db = null)
        {
            const string SQL = @"if(select count(1) from USERMACHINEGROUPMAP where USERIID={0})=0
            select a.MACHINEID,a.GROUPID,b.VIN,b.MACHINENAME,b.MACHINENAME2 from MACHINEGROUPMAP a,MACHINES b where a.MACHINEID=b.MACHINEID and ISNULL(b.HIDE,0)=0 
            else
            select a.MACHINEID,a.GROUPID,b.VIN,b.MACHINENAME,b.MACHINENAME2 from MACHINEGROUPMAP a,MACHINES b where a.MACHINEID=b.MACHINEID and ISNULL(b.HIDE,0)=0
            and b.MACHINEID in (select distinct MACHINEID from MACHINEGROUPMAP
            where GROUPID in (select GROUPID from USERMACHINEGROUPMAP where USERIID={0}))";

            if (db == null)
                db = SystemParams.GetDbInstance();
            DataTable dt = null;
            dt = db.GetDataTableBySQL(SQL, useriid);

            Dictionary<string, List<MachineViewItem>> result = new Dictionary<string, List<MachineViewItem>>(StringComparer.OrdinalIgnoreCase);
            if (dt.Rows.Count == 0)
            {
                return result;
            }
            foreach (DataRow dr in dt.Rows)
            {
                MachineViewItem mi = new MachineViewItem();
                mi.ID = FIDbAccess.GetFieldInt64(dr["MACHINEID"], 0);
                mi.Name = FIDbAccess.GetFieldString(dr["MACHINENAME"], string.Empty);
                mi.Name2 = FIDbAccess.GetFieldString(dr["MACHINENAME2"], string.Empty);
                mi.VIN = FIDbAccess.GetFieldString(dr["VIN"], string.Empty);
                string groupID = FIDbAccess.GetFieldString(dr["GROUPID"], string.Empty);
                if (!result.ContainsKey(groupID))
                    result[groupID] = new List<MachineViewItem>();
                result[groupID].Add(mi);
            }
            return result;
        }

        private static void ConvertSpeedUnitToMile(LocationViewItem loc)
        {
            if (loc == null) return;
            if (loc.Speed >= 0 && loc.SpeedUnit.StartsWith("K", StringComparison.OrdinalIgnoreCase))
            {
                loc.Speed = loc.Speed * 0.6213712;
                loc.SpeedUnit = "mi/h";
            }
            if (loc.PostedSpeed > 0 && loc.PostedSpeedUnit.StartsWith("K", StringComparison.OrdinalIgnoreCase))
            {
                loc.PostedSpeed = loc.PostedSpeed * 0.6213712;
                loc.PostedSpeedUnit = "mi/h";
            }
        }

        public static AssetLocationHistoryViewItem GetMachineLocationHistory(string sessionid, string machineid, DateTime startTime, DateTime endTime, string companyid, bool notShow00loc, string datasource)
        {
            if (string.IsNullOrEmpty(companyid))
                companyid = SystemParams.CompanyID;

            var client = FleetServiceClientHelper.CreateClient<AssetQueryClient>(companyid, sessionid);
            AssetBasicInfo asset = client.GetAssetBasicInfoByID(companyid, Convert.ToInt64(machineid));
            AssetViewItem ai = new AssetViewItem();
            Helper.CloneProperty(ai, asset);

            double timeOffset = SystemParams.GetHoursOffset();
            startTime = startTime.AddHours(-timeOffset);
            endTime = endTime.AddHours(-timeOffset);

            AssetLocationInfo[] assetLocs = client.GetAssetBasicLocationHistory(companyid, long.Parse(machineid), startTime, endTime, datasource, "", !notShow00loc);

            List<LocationViewItem> ls = new List<LocationViewItem>();
            foreach (AssetLocationInfo assetLoc in assetLocs)
            {
                LocationViewItem li = new LocationViewItem();
                li.Latitude = assetLoc.Latitude;
                li.Longitude = assetLoc.Longitude;
                li.LocationTime = assetLoc.AsofTime.AddHours(timeOffset);

                li.Speed = assetLoc.Speed;
                li.SpeedUnit = assetLoc.SpeedUnits;
                li.PostedSpeed = assetLoc.PostedSpeedLimit;
                li.PostedSpeedUnit = assetLoc.SpeedLimitUnits;
                li.Street = assetLoc.Street;
                li.HarshDringEvent = assetLoc.HarshDringEvent;
                li.SpeedingBehavior = assetLoc.SpeedingBehavior;
                li.IconURL = GenerateLocationIconUrl(assetLoc);
                li.SmartWitnessVideoUrl = assetLoc.SmartWitnessVideoUrl;

                ConvertSpeedUnitToMile(li);
                ls.Add(li);
            }
            AssetLocationHistoryViewItem al = new AssetLocationHistoryViewItem();
            al.Machine = ai;
            al.Locations = ls.ToArray();
            return al;
        }

        private static string GenerateLocationIconUrl(AssetLocationInfo loc)
        {
            //http://iron.soft.rz/admin/machinetypeicon.ashx
            //http://iron.soft.rz/admin/machinemovingicon.ashx
            string path = SystemParams.MachineTypeMapViewIconUrl.ToLower().Replace("machinetypeicon.ashx", "machinemovingicon.ashx");
            const string PARAM = "?tp={0}&bkcolor={1}&heading={2}";
            int tp = (int)HarshDrivingEvents.HardAccelerationEvent;
            string color = "";
            switch (loc.HarshDringEvent)
            {
                case HarshDrivingEvents.None:
                    break;
                case HarshDrivingEvents.HardAccelerationEvent:
                    color = "#ff3f48cc";
                    break;
                case HarshDrivingEvents.HardBrakeEvent:
                    color = "#ff00a8f3";
                    break;
                case HarshDrivingEvents.HardTurnEvent:
                    color = "#fffff200";
                    break;
            }
            if (string.IsNullOrEmpty(color))
            {
                if (loc.SpeedingBehavior == SpeedingBehaviors.MinorSpeeding)
                    color = "#ffff7f27";
                else if (loc.SpeedingBehavior == SpeedingBehaviors.SevereSpeeding)
                    color = "#ffec1c24";
            }
            if (string.IsNullOrEmpty(color))
            {
                if (loc.MoveStatus == AssetMoveStatus.InMotion)
                    color = "#ff228B22";
            }

            if (loc.Speed <= 0 && loc.MoveStatus == AssetMoveStatus.Unknown)
                loc.Heading = -1;

            if (string.IsNullOrEmpty(color))
            {
                if (loc.MoveStatus == AssetMoveStatus.StoppedOn)
                    return path + "?legend=StoppedOn";
                else if (loc.MoveStatus == AssetMoveStatus.StoppedOff)
                    return path + "?legend=StoppedOff";
            }
            color = HttpUtility.UrlEncode(color);
            path = path + string.Format(PARAM, tp, color, loc.Heading);

            return path;
        }

        public static MapAlertViewDefinitionItem[] GetMapAlertViews(string sessionid, string companyid, string selectedViewID)
        {
            if (string.IsNullOrWhiteSpace(companyid))
                companyid = SystemParams.CompanyID;

            var client = FleetServiceClientHelper.CreateClient<MapViewQueryClient>(companyid, sessionid);
            AlertViewMapItem[] views = client.GetAlertViewMapItems(companyid);

            AlertViewMapItem viewInfo = null;
            try
            {
                if (!string.IsNullOrWhiteSpace(selectedViewID))//获取View下使用的数据源信息
                    viewInfo = client.GetAlertViewMapItem(companyid, selectedViewID);
            }
            catch { }

            string path = SystemParams.MachineTypeMapViewIconUrl;
            List<MapAlertViewDefinitionItem> ls = new List<MapAlertViewDefinitionItem>();
            foreach (AlertViewMapItem ai in views)
            {
                MapAlertViewDefinitionItem mi = new MapAlertViewDefinitionItem();
                mi.ID = ai.ID;
                mi.Name = ai.Name;

                if (viewInfo != null && viewInfo.ID.Equals(mi.ID, StringComparison.OrdinalIgnoreCase))
                {
                    mi.Layers = new MapAlertLayerDefinitionItem[viewInfo.Layers.Count];
                    for (int i = 0; i < viewInfo.Layers.Count; i++)
                    {
                        var layer = viewInfo.Layers[i];
                        mi.Layers[i] = new MapAlertLayerDefinitionItem();
                        mi.Layers[i].ID = layer.LayerId;
                        mi.Layers[i].Title = layer.Title;
                        mi.Layers[i].LegendUrl = layer.LegendUrl;

                        if (layer.Pivots != null && layer.Pivots.Count > 0)
                            mi.Layers[i].Pivots = ConvertPivotsDefine(layer.Pivots);
                    }
                    //mi.Layers = mi.Layers.OrderBy((l) => l.AlertLayerType).ToArray();
                    mi.LookupDataSources = ConvertLookupData(viewInfo.LookupDataSources);
                }
                ls.Add(mi);
            }
            return ls.OrderBy((mal) => mal.Name).ToArray();

        }

        private static List<LookupDataSourceDataItem> ConvertLookupData(List<LookupDataSourceData> data)
        {
            List<LookupDataSourceDataItem> result = new List<LookupDataSourceDataItem>();
            if (data != null)
            {
                foreach (LookupDataSourceData d in data)
                {
                    LookupDataSourceDataItem item = new LookupDataSourceDataItem();
                    item.ID = d.ID;
                    item.Name = d.Name;
                    item.Items.AddRange(d.Items);
                    result.Add(item);
                }
            }
            return result;
        }

        private static AlertLayerPivotViewItem[] ConvertPivotsDefine(List<AlertLayerPivot> paramerters)
        {
            List<AlertLayerPivotViewItem> list = new List<AlertLayerPivotViewItem>();
            foreach (AlertLayerPivot pd in paramerters)
            {
                AlertLayerPivotViewItem pi = new AlertLayerPivotViewItem();
                Helper.CloneProperty(pi, pd);
                if (pi.DataType == DataTypes.Datetime)
                {
                    try
                    {
                        pi.DefaultValue = DateTime.Parse(pi.DefaultValue).ToString("M/d/yyyy");
                    }
                    catch
                    {
                    }
                }
                list.Add(pi);
            }

            return list.ToArray();
        }

        public static long[] GetNoGroupAssets(string companyid)
        {
            const string SQL = @"select b.MACHINEID from MACHINES b where not exists(select 1 from MACHINEGROUPMAP a where a.MACHINEID=b.MACHINEID) and isnull(b.HIDE,0)=0";

            string dbs = SystemParams.GetCompanyDbString(companyid);
            FISqlConnection db = new FISqlConnection(dbs);
            if (db == null)
                db = SystemParams.GetDbInstance();
            DataTable dt = db.GetDataTableBySQL(SQL);

            List<long> result = new List<long>();
            if (dt.Rows.Count == 0)
            {
                return new long[0];
            }
            foreach (DataRow dr in dt.Rows)
            {
                result.Add(FIDbAccess.GetFieldInt64(dr["MACHINEID"], 0));
            }
            return result.ToArray();
        }
    }
}