using IronIntel.Contractor.FilterQ;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IronIntel.Contractor.Site
{
    public class FilterQBasePage : ContractorBasePage
    {
        protected void ProcessRequest()
        {
            string methodName = Request.QueryString["method"];
            if (methodName != null)
            {
                switch (methodName.ToUpper())
                {
                    case "GETFILTERQGROUPS":
                        GetFilterQGroups();
                        break;

                    case "SAVEFILTERQ":
                        SaveFilterQ();
                        break;
                }
            }
        }

        private FilterQItem ConvertToFilterQItem(MachineTasksNotificationInfo c, bool isdealer)
        {
            var item = new FilterQItem
            {
                TaskID = c.TaskID,
                JobContact = c.JobContact,
                JobContactNumber = c.JobContactNumber,
                JobAddress1 = c.JobAddress1,
                JobAddress2 = c.JobAddress2,
                JobAddressCity = c.JobAddressCity,
                JobAddressState = c.JobAddressState,
                JobAddressZip = c.JobAddressZip,

                MachineID = c.MachineID,
                CurrentJob = c.CurrentJob,
                OrgMachineCode = c.OrgMachineCode,
                ManufactuerMake = c.ManufactuerMake,
                Model = c.Model,
                SN = (c.SN != null && c.SN.Length > 6) ? c.SN.Substring(c.SN.Length - 6) : c.SN,
                CumulativeHours = c.CumulativeHours,
                MachineTaskHourCheck = c.MachineTaskHourCheck,
                DiffToService = c.DiffToService,
                EstDueDate = c.ESTServiceNeededBy.ToString("M/d/yyyy"),
                EstShipDate = c.ESTShopDate.ToString("M/d/yyyy"),

                TaskComplete = c.TaskComplete,
                UPSTrackingNumber = c.UPSTrackingNumber,
                TaskCompletedHours = c.TaskCompletedHours,
                RequestJREToService = c.RequestJREToService,
                Approved = c.Approved,
                Priority = c.Priority,
                CustomerPO = c.CustomerPO,
                CustomerWO = c.CustomerWO,
                AlternateAddress1 = c.AlternateAddress1,
                AlternateAddress2 = c.AlternateAddress2,
                AlternateAddressCity = c.AlternateAddressCity,
                AlternateAddressState = c.AlternateAddressState,
                AlternateAddressZip = c.AlternateAddressZip,
                AltJob = c.AltJob,
                AltJobSiteContact = c.AltJobSiteContact,
                ShipNotes = c.ShipNotes
            };
            if (isdealer)
            {
                item.OrganizationName = c.OrganizationName;
            }
            return item;
        }

        private void GetFilterQGroups()
        {
            try
            {
                // query shipdates
                var s = Request.Form["ClientData"];
                var query = JsonConvert.DeserializeObject<FilterQueryParam>(s);


                FilterQGroupByShipDate[] items;
                if (GetCurrentLoginSession() != null)
                {
                    var isdealer = SystemParams.CustomerDetail.IsDealer;
                    var datas = FilterQManagememt.GetTasksNotofications().ToList();
                    // sort datas
                    var comparer = new FilterQItemComparer { Query = query };
                    if (string.IsNullOrWhiteSpace(query.ColumnSort))
                    {
                        // default sort: Est Ship Date desc
                        datas.Sort((m1, m2) => m2.ESTShopDate.CompareTo(m1.ESTShopDate));
                    }
                    else
                    {
                        datas.Sort(comparer);
                    }

                    var lst = new List<FilterQGroupByShipDate>();

                    // 组织 shipdates
                    var shipdates = datas.Distinct(new ShipDateEqualityComparer())
                        .Select(m => m.ESTShopDate.ToString("M/d/yyyy"))
                        .OrderBy(d => d);
                    var shipgroup = new FilterQGroupByShipDate
                    {
                        ShipDates = shipdates.ToArray(),
                        SelectedShipDates = query.ShipDates
                    };
                    IEnumerable<MachineTasksNotificationInfo> dts = datas;
                    if (query.ShipDates != null && query.ShipDates.Length > 0)
                    {
                        dts = datas.Where(m => query.ShipDates.Contains(m.ESTShopDate.ToString("M/d/yyyy")));
                    }
                    else
                    {
                        dts = datas;
                    }

                    var notifications = dts.ToArray();
                    var result = notifications.GroupBy(g => g.CurrentJob);
                    var list = new List<FilterQGroup>();
                    foreach (var g in result)
                    {
                        var subresult = g.GroupBy(gr => gr.OrganizationName);
                        foreach (var og in subresult)
                        {
                            var ogs = og.ToArray();

                            var group = new FilterQGroup
                            {
                                JobSite = g.Key,
                                OrganizationName = og.Key,
                            };
                            var children = new List<FilterQItem>();
                            // combine address
                            for (int i = 0; i < ogs.Length; i++)
                            {
                                var c = ogs[i];
                                if (query.TaskComplete >= 0 && query.TaskComplete == (c.TaskComplete ? 0 : 1))
                                {
                                    continue;
                                }
                                children.Add(ConvertToFilterQItem(c, isdealer));
                                if (group.JobContact == null)
                                {
                                    group.JobContact = c.JobContact;
                                }
                            }
                            group.Children = children.ToArray();
                            list.Add(group);
                        }
                    }
                    shipgroup.Groups = list.ToArray();

                    lst.Add(shipgroup);
                    //}
                    items = lst.ToArray();
                }
                else
                {
                    throw new Exception("not login.");
                }
                string json = JsonConvert.SerializeObject(items);
                Response.Write(json);
            }
            catch (Exception ex)
            {
                Response.Write(JsonConvert.SerializeObject(ex.Message));
                AddLog("ERROR", "FilterQBasePage.GetFilterQGroups", ex.Message, ex.ToString());
            }
            Response.End();
        }

        private void SaveFilterQ()
        {
            try
            {
                if (GetCurrentLoginSession() != null)
                {
                    //var s = new System.IO.StreamReader(Request.InputStream).ReadToEnd();
                    //int i = s.IndexOf("&ClientData=");
                    //if (i < 0)
                    //{
                    //    Response.Write("false");
                    //}
                    //else
                    {
                        //s = s.Substring(i + 12);
                        //s = System.Web.HttpUtility.UrlDecode(s);

                        var s = Request.Form["ClientData"];
                        s = System.Web.HttpUtility.HtmlDecode(s);

                        var array = JsonConvert.DeserializeObject<MachineTasksNotificationInfo[]>(s);
                        FilterQManagememt.SaveMachineTasks(array, GetCurrentLoginSession().User.UID);

                        Response.Write("true");
                    }
                }
                else
                {
                    Response.Write("false");
                }
            }
            catch (Exception ex)
            {
                Response.Write(JsonConvert.SerializeObject(ex.Message));
            }
            Response.End();
        }
    }

    public class ShipDateEqualityComparer : IEqualityComparer<MachineTasksNotificationInfo>
    {
        public bool Equals(MachineTasksNotificationInfo x, MachineTasksNotificationInfo y)
        {
            if (x == null || y == null)
            {
                return x == y;
            }
            return x.ESTShopDate == y.ESTShopDate;
        }

        public int GetHashCode(MachineTasksNotificationInfo obj)
        {
            return obj == null ? 0 : obj.ESTShopDate.GetHashCode();
        }
    }

    public class FilterQItemComparer : IComparer<MachineTasksNotificationInfo>
    {
        public FilterQueryParam Query { get; set; }

        public int Compare(MachineTasksNotificationInfo m1, MachineTasksNotificationInfo m2)
        {
            switch (Query.ColumnSort)
            {
                case "ORGANIZATION NAME":
                    return Query.IsAsc
                        ? string.Compare(m1.OrganizationName, m2.OrganizationName, true)
                        : string.Compare(m2.OrganizationName, m1.OrganizationName, true);
                case "EQUIPMENT CODE":
                    return Query.IsAsc
                        ? string.CompareOrdinal(m1.OrgMachineCode, m2.OrgMachineCode)
                        : string.CompareOrdinal(m2.OrgMachineCode, m1.OrgMachineCode);
                case "CURRENT JOBSITE":
                    return Query.IsAsc
                        ? string.CompareOrdinal(m1.CurrentJob, m2.CurrentJob)
                        : string.CompareOrdinal(m2.CurrentJob, m1.CurrentJob);
                case "JOBSITE CONTACT":
                    return Query.IsAsc
                        ? string.CompareOrdinal(m1.JobContact, m2.JobContact)
                        : string.CompareOrdinal(m2.JobContact, m1.JobContact);
                case "INFO":
                    return Query.IsAsc
                        ? string.CompareOrdinal(m1.ManufactuerMake, m2.ManufactuerMake)
                        : string.CompareOrdinal(m2.ManufactuerMake, m1.ManufactuerMake);
                case "ESTIMATED SHIP DATE":
                    return Query.IsAsc
                        ? DateTime.Compare(m1.ESTShopDate, m2.ESTShopDate)
                        : DateTime.Compare(m2.ESTShopDate, m1.ESTShopDate);
                case "HOURS TO SERVICE":
                    return Query.IsAsc
                        ? m1.DiffToService.CompareTo(m2.DiffToService)
                        : m2.DiffToService.CompareTo(m1.DiffToService);
                case "TASK COMPLETE?":
                    return Query.IsAsc
                        ? m1.TaskComplete.CompareTo(m2.TaskComplete)
                        : m2.TaskComplete.CompareTo(m1.TaskComplete);
                case "UPS TRACKING NUMBER":
                    return Query.IsAsc
                        ? string.CompareOrdinal(m1.UPSTrackingNumber, m2.UPSTrackingNumber)
                        : string.CompareOrdinal(m2.UPSTrackingNumber, m1.UPSTrackingNumber);
                case "REQUEST JRE TO SERVICE":
                    return Query.IsAsc
                        ? m1.RequestJREToService.CompareTo(m2.RequestJREToService)
                        : m2.RequestJREToService.CompareTo(m1.RequestJREToService);
                case "APPROVED":
                    return Query.IsAsc
                        ? m1.Approved.CompareTo(m2.Approved)
                        : m2.Approved.CompareTo(m1.Approved);
                case "WONUMBER":
                    return Query.IsAsc
                        ? string.CompareOrdinal(m1.CustomerWO, m2.CustomerWO)
                        : string.CompareOrdinal(m2.CustomerWO, m1.CustomerWO);
                case "SHIP NOTES":
                    return Query.IsAsc
                        ? string.CompareOrdinal(m1.ShipNotes, m2.ShipNotes)
                        : string.CompareOrdinal(m2.ShipNotes, m1.ShipNotes);
                case "PO":
                    return Query.IsAsc
                        ? string.Compare(m1.CustomerPO, m2.CustomerPO)
                        : string.Compare(m2.CustomerPO, m1.CustomerPO);

                default:
                    return 0;
            }
        }
    }

    public class FilterQGroupByShipDate
    {
        public string[] ShipDates { get; set; }
        public string[] SelectedShipDates { get; set; }
        public FilterQGroup[] Groups { get; set; }
    }

    public class FilterQGroup
    {
        public string JobSite { get; set; }
        public string JobContact { get; set; }
        public string OrganizationName { get; set; }
        public FilterQItem[] Children { get; set; }
    }

    public class FilterQItem : MachineTasksNotificationInfo
    {
        public string EstDueDate { get; set; }
        public string EstShipDate { get; set; }
    }

    public class FilterQueryParam
    {
        public string ColumnSort { get; set; }
        public bool IsAsc { get; set; }
        // -1: All, 0: No, 1: Yes
        public int TaskComplete { get; set; }
        public string[] ShipDates { get; set; }
    }
}
