using System;
using System.Collections.Generic;

using BeWo.Data.Access;
using BeWo.Data.Entities;

using BS.Shared;
using BS.Shared.DataContracts;
using BS.Shared.Extensions;

namespace BeWo.Report.ReportObjects
{
    public class FLSReportRO : AbstractBeWoReportObject<FLSReportRO>
    {
        private List<FLSReportGroup> _FLSReportGroups = new List<FLSReportGroup>();

        public List<FLSReportGroup> FLSReportGroups
        {
            get
            {
                return this._FLSReportGroups;
            }

            set
            {
                this._FLSReportGroups = value;
            }
        }

        public string GroupTypeHeader { get; set; }

        public DateTime? ReportEndDate { get; set; }

        public DateTime? ReportStartDate { get; set; }

        public DateTime? SupportConceptEndDate { get; set; }

        public DateTime? SupportConceptStartDate { get; set; }

        public decimal TotalFLM { get; set; }

        public string TotalHourMinuteString { get; set; }

        public static FLSReportRO Create(FLSAnalysisDataReportDC dc)
        {
            var result = new FLSReportRO();
            long starttime = DateTime.Now.Ticks;

            result.ReportStartDate = dc.ReportStartDate;
            result.ReportEndDate = dc.ReportEndDate;
            result.TotalFLM = dc.TotalFLM;

            int h = (int)Math.Floor(result.TotalFLM / 60);
            int m = (int)result.TotalFLM % 60;

            result.TotalHourMinuteString = String.Format("{0}:{1:00}", h, m);

            if (dc.ReportType == 0)
            {
                result.GroupTypeHeader = "Klient/in";
            }
            else if (dc.ReportType == 1)
            {
                result.GroupTypeHeader = "Mitarbeiter/in";
            }
            else if (dc.ReportType == 2)
            {
                result.GroupTypeHeader = "Kostenträger";
            }

            foreach (var group in dc.Groups)
            {
                FLSReportGroup reportGroup = new FLSReportGroup();
                reportGroup.TotalFLM = group.TotalFLM;
                h = (int)Math.Floor(reportGroup.TotalFLM / 60);
                m = (int)reportGroup.TotalFLM % 60;

                reportGroup.TotalHourMinuteString = String.Format("{0}:{1:00}", h, m);
                reportGroup.Name = group.Name;
                reportGroup.CustomValue1 = group.CustomField1;
                reportGroup.CustomValue2 = group.CustomField2;
                reportGroup.CustomValue3 = group.CustomField3;
                reportGroup.CustomValue4 = group.CustomField4;
                reportGroup.CustomValue5 = group.CustomField5;

                Contract lastContract = null;
                Employee emp = null;

                if (group.Oid != null)
                {
                    reportGroup.ObjectOid = group.Oid.Value;

                    Person p = null;
                    if (dc.ReportType == 0)
                    {
                        emp = DAOFactory.GenericDAO.LoadByID<Employee>(group.Oid.Value);

                        if (emp != null)
                        {
                            lastContract = emp.GetValidContractForDate(dc.ReportEndDate);

                            p = emp.Person;

                            reportGroup.MaxPayment = Decimal.MaxValue;

                        }
                    }
                    else if (dc.ReportType == 1)
                    {
                        Customer cust = DAOFactory.GenericDAO.LoadByID<Customer>(group.Oid.Value);

                        if (cust != null)
                        {
                            p = cust.Person;
                        }
                    }

                    if (p != null)
                    {
                        reportGroup.PersonSalutation = p.Sex == Sex.Female
                                                           ? "Frau"
                                                           : "Herr";
                        reportGroup.PersonFirstName = p.FirstName;
                        reportGroup.PersonLastName = p.LastName;

                        if (p.Address != null)
                        {
                            reportGroup.PersonStreet = p.Address.Street;
                            reportGroup.PersonPostalCode = p.Address.PostalCode;
                            reportGroup.PersonCity = p.Address.Town;
                        }
                    }
                }

                

                if (lastContract != null)
                {
                    reportGroup.EmployeeHourlyRate = lastContract.HourlyRate;
                    reportGroup.EmployeeWeeklyFLS = lastContract.WeeklyFLS;

                }

                if (emp != null)
                {
                    decimal maxpayment = 0;

                    Contract cstart = emp.GetValidContractForDate(dc.ReportStartDate);
                    Contract cend = emp.GetValidContractForDate(dc.ReportEndDate);
                    if (cstart != null && cstart.HourlyRate.HasValue && cstart.WeeklyTotalHours.HasValue && cend != null)
                    {
                        if (cstart.Oid.Value == cend.Oid.Value || !cend.EntryDate.HasValue)
                        {
                            maxpayment = cstart.HourlyRate.Value * cstart.WeeklyTotalHours.Value * 4;
                        }
                        else
                        {
                            decimal totalHoursPerDay = cstart.WeeklyTotalHours.Value / 7m;
                            DateTime end = cend.EntryDate.Value;
                            TimeSpan ts = end.Subtract(dc.ReportStartDate.Value);
                            int days = (int)ts.TotalDays;

                            maxpayment = totalHoursPerDay * cstart.HourlyRate.Value * days;

                            Contract c2 = emp.GetValidContractForDate(end.AddDays(1));
                            if (c2 != null && c2.HourlyRate.HasValue && c2.WeeklyTotalHours.HasValue)
                            {
                                decimal totalHoursPerDay2 = c2.WeeklyTotalHours.Value / 7m;
                                TimeSpan ts2 = dc.ReportEndDate.Value.Subtract(end);
                                int days2 = (int)ts2.TotalDays + 1;

                                maxpayment += totalHoursPerDay2 * c2.HourlyRate.Value * days2;
                            }
                        }
                        

                    }
                    if (lastContract != null)
                    {
                        if (lastContract.WeeklyTotalHours != null)
                        {
                            reportGroup.EmployeePrePayment = reportGroup.EmployeeHourlyRate * lastContract.WeeklyTotalHours * 4;
                        }
                    }
                    reportGroup.EmployeePrePayment = maxpayment;
                }

                decimal gesamtBetrag = 0;

                foreach (var detail in group.Details)
                {
                    FLSReportDetail reportDetail = new FLSReportDetail();
                    reportDetail.Name = detail.Name;
                    reportDetail.CustomValue1 = detail.CustomValue1;
                    reportDetail.CustomValue2 = detail.CustomValue2;
                    reportDetail.CustomValue3 = detail.CustomValue3;

                    decimal flm = 0;
                    foreach (var sr in detail.ServiceRecords)
                    {
                        FLSReportServiceRecord reportSR = new FLSReportServiceRecord();

                        reportSR.EmployeeOid = sr.EmployeeOid;
                        reportSR.CustomerOid = sr.CustomerOid;
                        reportSR.CostBearer2SupportConceptOid = sr.CostBearer2SupportConceptOid;

                        reportSR.Start = sr.Start;
                        reportSR.End = sr.End;

                        if (sr.Start != null && sr.Start.Value.Second == 0)
                        {
                            reportSR.StartTime = sr.Start;

                            DateTime endDt = sr.Start.Value.AddMinutes((double)sr.RoundedDuration);
                            if (sr.GroupOid.HasValue && sr.GroupRoundedDuration.HasValue)
                                endDt = sr.Start.Value.AddMinutes((double)sr.GroupRoundedDuration);

                            reportSR.EndTime = endDt;

                            reportSR.TimeRange = String.Format("{0:HH:mm} - {1:HH:mm}", reportSR.Start, endDt);
                        }

                        
                        // reportSR.InsertedOn = sr.InsertedOn;
                        // reportSR.InsUser = sr.InsUser;
	                    reportSR.ServiceRecordOid = sr.ServiceRecordOid;
	                    reportSR.DistanceInMeter = sr.DistanceInMeter;
                        reportSR.Notice = sr.Notice;
                        reportSR.RoundedDuration = sr.RoundedDuration;
                        flm += sr.RoundedDuration;

                        if (emp != null)
                        {
                            Contract con = emp.GetValidContractForDate(sr.Start);
                            if (con != null && con.HourlyRate.HasValue)
                            {
                                gesamtBetrag += con.HourlyRate.Value * (sr.RoundedDuration / 60);
                            }
                        }

                        if (reportSR.Start != null && reportSR.End != null)
                        {
                            TimeSpan ts = reportSR.End.Value.Subtract(reportSR.Start.Value);

                            reportSR.Duration = ts.GetTotalMinutes();
                        }

                        if (sr.ServiceDescription != null)
                        {
                            reportSR.ServiceDescription = sr.ServiceDescription.Name;
                            reportSR.ServiceCategory = sr.ServiceDescription.CategoryName;
                            reportSR.ServiceDescriptionAbbr = sr.ServiceDescription.Abbreviation;
                            reportSR.ServiceCategoryAbbr = sr.ServiceDescription.Category.Abbreviation;
                        }

                        if (sr.GroupOid != null && sr.GroupPersonCount != null)
                        {
                            reportSR.GroupName = "Gruppe (" + sr.GroupPersonCount.Value + " Teilnehmer)";
                        }
                        else
                        {
                            reportSR.GroupName = sr.GroupName;
                            reportSR.GroupName = "Sonstiges".Equals(sr.GroupName)
                                                     ? string.Empty
                                                     : sr.GroupName;
                        }

                        if (dc.ShowGroups)
                        {
                            reportDetail.ServiceRecords.Add(reportSR);
                        }
                        else
                        {
                            reportGroup.ServiceRecords.Add(reportSR);
                        }
                    }

                    reportDetail.TotalFLM = flm;
                    h = (int)Math.Floor(reportDetail.TotalFLM / 60);
                    m = (int)reportDetail.TotalFLM % 60;

                    reportDetail.TotalHourMinuteString = String.Format("{0}:{1:00}", h, m);
                    if (dc.ShowGroups)
                    {
                        reportGroup.FLSReportDetails.Add(reportDetail);
                    }
                }

                //reportGroup.EmployeePayment = reportGroup.EmployeeHourlyRate * (reportGroup.TotalFLM / 60);
                reportGroup.EmployeePayment = gesamtBetrag;

                if (lastContract != null && lastContract.EmploymentType != null && reportGroup.EmployeePayment != null && reportGroup.EmployeePayment.Value > 0)
                {
                    reportGroup.EmploymentTypeOid = lastContract.EmploymentType.Oid;
                }

                result.FLSReportGroups.Add(reportGroup);
            }

            long endtime = DateTime.Now.Ticks;

            long diff = endtime - starttime;
            double secs = diff / (double)10000000;

            return result;
        }

        public class FLSReportDetail
        {
            private List<FLSReportServiceRecord> _ServiceRecords = new List<FLSReportServiceRecord>();

            public string Name { get; set; }

            public List<FLSReportServiceRecord> ServiceRecords
            {
                get
                {
                    return this._ServiceRecords;
                }

                set
                {
                    this._ServiceRecords = value;
                }
            }

            public decimal TotalFLM { get; set; }

            public string TotalHourMinuteString { get; set; }

            public long ObjectOid { get; set; }

            public String CustomValue1 { get; set; }

            public String CustomValue2 { get; set; }

            public String CustomValue3 { get; set; }
        }

        public class FLSReportGroup
        {
            private List<FLSReportDetail> _FLSReportDetails = new List<FLSReportDetail>();

            private List<FLSReportServiceRecord> _ServiceRecords = new List<FLSReportServiceRecord>();

            public decimal? EmployeeHourlyRate { get; set; }

            public decimal? EmployeePayment { get; set; }

            public decimal? EmployeePrePayment { get; set; }

            public decimal? EmployeeWeeklyFLS { get; set; }

            public long? EmploymentTypeOid { get; set; }

            public List<FLSReportDetail> FLSReportDetails
            {
                get
                {
                    return this._FLSReportDetails;
                }

                set
                {
                    this._FLSReportDetails = value;
                }
            }

            public decimal MaxPayment { get; set; }

            public string Name { get; set; }

            public string PersonCity { get; set; }

            public string PersonFirstName { get; set; }

            public string PersonLastName { get; set; }

            public string PersonPostalCode { get; set; }

            public string PersonSalutation { get; set; }

            public string PersonStreet { get; set; }

            public List<FLSReportServiceRecord> ServiceRecords
            {
                get
                {
                    return this._ServiceRecords;
                }

                set
                {
                    this._ServiceRecords = value;
                }
            }

            public decimal TotalFLM { get; set; }

            public string TotalHourMinuteString { get; set; }

            public long ObjectOid { get; set; }

            public String CustomValue1 { get; set; }

            public String CustomValue2 { get; set; }

            public String CustomValue3 { get; set; }

            public String CustomValue4 { get; set; }

            public String CustomValue5 { get; set; }
        }

        public class FLSReportServiceRecord
        {
            public decimal Duration { get; set; }

            public DateTime? End { get; set; }

            public DateTime? EndTime { get; set; }

            public string[] Goals { get; set; }

            public string GroupName { get; set; }

            public string InsUser { get; set; }

            public DateTime? InsertedOn { get; set; }

            public string Notice { get; set; }

            public decimal RoundedDuration { get; set; }

            public string ServiceCategory { get; set; }

            public string ServiceDescription { get; set; }

            public string ServiceCategoryAbbr { get; set; }

            public string ServiceDescriptionAbbr { get; set; }

            public DateTime? Start { get; set; }

            public DateTime? StartTime { get; set; }

            public string TimeRange { get; set; }

            public long? CustomerOid { get; set; }

            public long? EmployeeOid { get; set; }

            public long? CostBearer2SupportConceptOid { get; set; }

            public String CustomValue1 { get; set; }

            public String CustomValue2 { get; set; }

            public String CustomValue3 { get; set; }

            public String CustomValue4 { get; set; }

            public String CustomValue5 { get; set; }

			public int? DistanceInMeter { get; set; }

			public long? ServiceRecordOid { get; set; }
		}
    }
}