using Foresight.Fleet.Services.Asset;
using Foresight.Fleet.Services.AssetHealth;
using IronIntel.Contractor.Machines;
using IronIntel.Contractor.Maintenance;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace IronIntel.Contractor.Site.Maintenance
{
    public class PreventativeMaintenanceBasePage : ContractorBasePage
    {
        protected void ProcessRequest(string methodName)
        {
            object result = null;

            try
            {
                if (methodName != null)
                {
                    switch (methodName.ToUpper())
                    {
                        case "GETPMSCHEDULE":
                            result = GetPmSchedule();
                            break;
                        case "DELETEPMSCHEDULE":
                            result = DeletePmScheule();
                            break;
                        case "SAVEPMSCHEDULE":
                            result = SavePmSchedule();
                            break;
                        case "ADDPMINTERVAL":
                            result = AddPmInterval();
                            break;
                        case "UPDATEPMINTERVAL":
                            result = UpdatePmInterval();
                            break;
                        case "DELETEPMINTERVAL":
                            result = DeletePmInterval();
                            break;

                        case "GETMACHINETYPES":
                            Machines.MachineManagement.RefreshMachineTypes();
                            result = MachineManagement.GetMachineTypes().OrderBy(m => m.Name).Select(t => new
                            {
                                ID = t.ID,
                                Name = t.Name
                            });
                            break;
                        case "GETMACHINELIST":
                            result = GetMachineList();
                            break;
                        case "GETSELECTEDMACHINES":
                            result = GetSelectedMachines();
                            break;
                        case "SAVEMACHINES":
                            result = SaveMachines();
                            break;
                        case "REMOVEPMASSETS":
                            result = RemovePMAssets();
                            break;
                        case "GETPMINTERVALBYSCHEDULEID":
                            result = GetPmIntervalByScheduleID();
                            break;
                        case "GETPMSCHEDULEBYID":
                            result = GetPMScheduleByID();
                            break;
                        case "GETMAINTENANCESCHEDULES":
                            result = GetMaintenanceSchedules();
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                result = ex.Message;
                SystemParams.WriteLog("Error", "PreventativeMaintenanceBasePage.ProcessRequest", ex.Message, ex.ToString());
            }

            string json = JsonConvert.SerializeObject(result);
            Response.Write(json);
            Response.End();
        }

        private object GetPmIntervalByScheduleID()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {

                    string scheduleid = Request.Form["ClientData"];
                    return MaintenanceManagement.GetPmInterval(session.SessionID, scheduleid);
                }
                else
                    return new PmIntervalItem[0];
            }
            catch (Exception ex)
            {
                AddLog("ERROR", "PreventativeMaintenanceBasePage.GetPmIntervalByScheduleID", ex.Message, ex.ToString());
                return ex.Message;
            }
        }


        private object GetPmSchedule()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {
                    string pmtype = Request.Form["ClientData"];
                    if (string.IsNullOrWhiteSpace(pmtype))
                        pmtype = "PM";

                    return MaintenanceManagement.GetPmSchedule(session.SessionID, pmtype, string.Empty, string.Empty);
                }
                else
                    return new PmScheduleInfo[0];
            }
            catch (Exception ex)
            {
                AddLog("ERROR", "PreventativeMaintenanceBasePage.GetPmSchedule", ex.Message, ex.ToString());
                return ex.Message;
            }
        }

        private object GetMaintenanceSchedules()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {
                    var clientdata = Request.Form["ClientData"];
                    string[] param = JsonConvert.DeserializeObject<string[]>(clientdata);
                    var pmtype = param[0];
                    var pmid = param[1];
                    var filter = HttpUtility.HtmlDecode(param[2]);

                    return MaintenanceManagement.GetPmSchedule(session.SessionID, pmtype, pmid, filter);
                }
                else
                    return new PmScheduleInfo[0];
            }
            catch (Exception ex)
            {
                AddLog("ERROR", "PreventativeMaintenanceBasePage.GetPmSchedule", ex.Message, ex.ToString());
                return ex.Message;
            }
        }

        private object GetPMScheduleByID()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {
                    string scheduleid = Request.Form["ClientData"];

                    return MaintenanceManagement.GetPMScheduleByID(session.SessionID, scheduleid);
                }
                else
                    return null;
            }
            catch (Exception ex)
            {
                AddLog("ERROR", "PreventativeMaintenanceBasePage.GetPMScheduleByID", ex.Message, ex.ToString());
                return ex.Message;
            }
        }

        private object DeletePmScheule()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {

                    var iid = Request.Form["ClientData"];
                    CreateClient<PMClient>().DeletePMSchedule(SystemParams.CompanyID, iid, session.User.UID);
                    return string.Empty;
                }
                else
                    return "Failed";

            }
            catch (Exception ex)
            {
                return "Failed to delete schedule: " + ex.Message;
            }
        }

        private object SavePmSchedule()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {
                    var s = HttpUtility.HtmlDecode(Request.Form["ClientData"]);
                    var item = JsonConvert.DeserializeObject<ScheduleSaveArgs>(s);

                    if (string.IsNullOrWhiteSpace(item.Name))
                    {
                        return "The schedule name cannot be empty or just whitespaces.";
                    }

                    PmScheduleInfo si;
                    if (item.Intervals == null)
                    {
                        item.Intervals = new PmIntervalItem[0];
                    }
                    else
                    {
                        for (int i = 0; i < item.Intervals.Length; i++)
                        {
                            if (string.IsNullOrEmpty(item.Intervals[i].PmIntervalID))
                                item.Intervals[i].PmIntervalID = Guid.NewGuid().ToString();
                            item.Intervals[i].ServiceName = item.Intervals[i].ServiceName.Trim();
                        }
                    }
                    si = new PmScheduleInfo
                    {
                        PmScheduleID = string.IsNullOrWhiteSpace(item.IID) ? Guid.NewGuid().ToString() : item.IID,
                        PmScheduleName = item.Name.Trim(),
                        PmScheduleType = item.Type,
                        PmScheduleUom = item.ScheduleUom,
                        Notes = item.Notes,
                        Intervals = item.Intervals
                    };
                    MaintenanceManagement.UpdatePmSchedule(session.SessionID, si, session.User.UID);

                    return si.PmScheduleID;
                }
                else
                    return "Failed";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private string AddPmInterval()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {
                    var s = HttpUtility.HtmlDecode(Request.Form["ClientData"]);
                    PmScheduleInfo item;
                    item = JsonConvert.DeserializeObject<PmScheduleInfo>(s);
                    PmIntervalItem piclient = item.Intervals[0];
                    piclient.PmIntervalID = Guid.NewGuid().ToString();
                    piclient.ScheduleId = item.PmScheduleID;

                    if (string.IsNullOrWhiteSpace(piclient.ServiceName))
                    {
                        return "Service Name cannot be empty.";
                    }
                    else
                    {
                        piclient.ServiceName = piclient.ServiceName.Trim();
                    }

                    MaintenanceManagement.UpdatePmInterval(session.SessionID, piclient, session.User.UID);

                    return string.Empty;
                }
                else
                    return "Failed";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private object UpdatePmInterval()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {
                    var s = HttpUtility.HtmlDecode(Request.Form["ClientData"]);
                    PmIntervalItem item = JsonConvert.DeserializeObject<PmIntervalItem>(s);

                    if (string.IsNullOrWhiteSpace(item.ServiceName))
                    {
                        return "Service Name cannot be empty.";
                    }
                    else
                    {
                        item.ServiceName = item.ServiceName.Trim();
                    }

                    MaintenanceManagement.UpdatePmInterval(session.SessionID, item, session.User.UID);

                    return string.Empty;
                }
                else
                    return "Failed";
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private string DeletePmInterval()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {
                    var iid = Request.Form["ClientData"];
                    CreateClient<PMClient>().DeletePMIntervals(SystemParams.CompanyID, new string[] { iid }, session.User.UID);
                    return string.Empty;
                }
                else
                    return "Failed";

            }
            catch (Exception ex)
            {
                return "Failed to delete interval: " + ex.Message;
            }
        }

        private MaintenanceMachineInfo[] GetMachineList()
        {
            var session = GetCurrentLoginSession();
            var s = Request.Form["ClientData"];
            var type = JsonConvert.DeserializeObject<MachineItem>(s);

            var machines = MaintenanceManagement.GetMaintenanceMachines(session.SessionID, (int)type.MachineID, type.Name, session.User.UID)
                //.Where(m => !selected.Any(t => t.MachineID == m.MachineID))
                .OrderBy(m => m.VIN)
                .ToArray();

            return machines;
        }

        private PMAssetItem[] GetSelectedMachines()
        {
            try
            {
                var session = GetCurrentLoginSession();
                if (session != null)
                {
                    var iid = Request.Form["ClientData"];
                    List<PMAssetItem> result = new List<PMAssetItem>();
                    var assets = CreateClient<PMClient>().GetPMAssets(SystemParams.CompanyID, iid);
                    if (session.User.UserType < Foresight.Fleet.Services.User.UserTypes.Admin)
                    {
                        AssetBasicInfo[] allassets = CreateClient<AssetQueryClient>(SystemParams.CompanyID).GetAssetBasicInfoByUser(SystemParams.CompanyID, "", session.User.UID, 0);
                        var allassetids = allassets.Select(a => a.ID).ToList();
                        assets = assets.Where(a => allassetids.Contains(a.AssetId)).ToArray();
                    }
                    foreach (var asset in assets)
                    {
                        PMAssetItem a = new PMAssetItem();
                        Helper.CloneProperty(a, asset);
                        a.EngineHours = asset.CurrentEngineHours;
                        a.Odometer = asset.CurrentOdometer;
                        result.Add(a);
                    }
                    return result.ToArray();
                }
                else
                    return null;

            }
            catch (Exception ex)
            {
                return null;
            }
        }

        private string SaveMachines()
        {
            var u = GetCurrentUser();
            if (u != null)
            {
                var s = Request.Form["ClientData"];
                var p = JsonConvert.DeserializeObject<ScheduleAssetArgs>(s);
                //MaintenanceManagement.UpdatePmMachines(ids.IID, ids.Assets);
                List<PMAssetInfo> assets = new List<PMAssetInfo>();
                if (p.Assets != null)
                {
                    foreach (var a in p.Assets)
                    {
                        PMAssetInfo pmAsset = new PMAssetInfo();
                        pmAsset.AssetId = a.AssetId;
                        pmAsset.StartHours = a.StartHours;
                        pmAsset.StartOdometer = a.StartOdometer;
                        pmAsset.StartDate = a.StartDate;
                        pmAsset.StartIntervalValue = a.StartIntervalValue;
                        assets.Add(pmAsset);
                    }
                }
                CreateClient<PMClient>().UpdatePMScheduleAssets(SystemParams.CompanyID, p.IID, assets.ToArray(), u.IID);
            }

            return string.Empty;
        }

        private string RemovePMAssets()
        {
            var u = GetCurrentUser();
            if (u != null)
            {
                var s = Request.Form["ClientData"];
                var p = JsonConvert.DeserializeObject<RemovePMAssetsArgs>(s);

                CreateClient<PMClient>().DeleteAssetsFromSchedule(SystemParams.CompanyID, p.ScheduleID, p.Assets, u.IID);
            }

            return string.Empty;
        }

        class RemovePMAssetsArgs
        {
            public string ScheduleID { get; set; }
            public long[] Assets { get; set; }
        }

        class ScheduleAssetArgs
        {
            public string IID { get; set; }
            public PMAssetItem[] Assets { get; set; }
        }


        class PMAssetItem
        {
            public string ModelName { get; set; }
            public string Notes { get; set; }
            private double? _StartOdometer;
            public double? StartOdometer
            {
                get
                {
                    return _StartOdometer;
                }
                set
                {
                    if (value != null)
                        _StartOdometer = Math.Round(value.Value, 2);
                    else
                        _StartOdometer = value;
                }
            }
            public double? StartHours { get; set; }
            public DateTime? StartDate { get; set; }
            public int TypeID { get; set; }
            public string TypeName { get; set; }
            public int AlertsCount { get; set; }
            public int UnMaintainedAlert { get; set; }
            public string MakeName { get; set; }
            public string Name { get; set; }
            public string VIN { get; set; }
            public long AssetId { get; set; }
            public double? EngineHours { get; set; }

            private double? _Odometer;
            public double? Odometer
            {
                get
                {
                    return _Odometer;
                }
                set
                {
                    if (value != null)
                        _Odometer = Math.Round(value.Value, 2);
                    else
                        _Odometer = value;
                }
            }
            public string PMScheduleId { get; set; }
            public int? StartIntervalValue { get; set; }
            public string StartDateString
            {
                get
                {
                    if (StartDate == null)
                        return "";
                    else
                        return StartDate.Value.ToString("M/d/yyyy");
                }
            }
        }

        class ScheduleSaveArgs
        {
            public string IID { get; set; }
            public string Name { get; set; }
            public string ScheduleUom { get; set; }
            public string Type { get; set; }
            public string Notes { get; set; }

            public PmIntervalItem[] Intervals { get; set; }
        }
    }
}
