using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using HRM.BO;
using Ease.Core.Model;
using Ease.Core.DataAccess;
using Ease.Core.Utility;
using Microsoft.Data.SqlClient;

namespace HRM.DA
{
    #region MonthlyWorkPlan Service

    [Serializable]
    public class MonthlyWorkPlanService : ServiceTemplate, IMonthlyWorkPlanService
    {
        public MonthlyWorkPlanService()
        {
        }

        private void MapObject(MonthlyWorkPlan oMonthlyWorkPlan, DataReader oReader)
        {
            base.SetObjectID(oMonthlyWorkPlan, oReader.GetInt32("MonthlyWorkPlanID").Value);
            oMonthlyWorkPlan.DaySerial = oReader.GetInt32("DaySerial", 0);
            oMonthlyWorkPlan.WorkDate = oReader.GetDateTime("WorkDate").Value;
            oMonthlyWorkPlan.ShiftID = oReader.GetInt32("ShiftID", 0);
            oMonthlyWorkPlan.HolidayID = oReader.GetInt32("HolidayID", 0);
            oMonthlyWorkPlan.WorkPlanGroupID = oReader.GetInt32("WorkPlanGroupID", 0);
            oMonthlyWorkPlan.Type = (EnumWorkPlanDayType)oReader.GetInt32("Type").Value;
            oMonthlyWorkPlan.CreatedBy = oReader.GetInt32("CreatedBy", 0);
            oMonthlyWorkPlan.CreatedDate = oReader.GetDateTime("CreatedDate").Value;
            oMonthlyWorkPlan.ModifiedBy = oReader.GetInt32("ModifiedBy");
            oMonthlyWorkPlan.ModifiedDate = oReader.GetDateTime("ModifiedDate");

            this.SetObjectState(oMonthlyWorkPlan, Ease.Core.ObjectState.Saved);
        }

        protected override T CreateObject<T>(DataReader oReader)
        {
            MonthlyWorkPlan oMonthlyWorkPlan = new MonthlyWorkPlan();
            MapObject(oMonthlyWorkPlan, oReader);
            return oMonthlyWorkPlan as T;
        }

        protected MonthlyWorkPlan CreateObject(DataReader oReader)
        {
            MonthlyWorkPlan oMonthlyWorkPlan = new MonthlyWorkPlan();
            MapObject(oMonthlyWorkPlan, oReader);
            return oMonthlyWorkPlan;
        }

        #region Service implementation

        public List<MonthlyWorkPlan> Get(DateTime attnMonth, int payrollTypeID)
        {
            List<MonthlyWorkPlan> monthlyWorkPlans = new List<MonthlyWorkPlan>();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(MonthlyWorkPlanDA.Get(tc, attnMonth, payrollTypeID));
                monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
                dr.Close();
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return monthlyWorkPlans;
        }

        public List<MonthlyWorkPlan> GetByDateAndGroupID(DateTime dAssDate, int groupID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(MonthlyWorkPlanDA.GetByDateAndGroupID(tc, dAssDate, groupID));
                var monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
                dr.Close();
                tc.End();
                return monthlyWorkPlans;
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public List<MonthlyWorkPlan> Get(DateTime fromdate, DateTime todate, int payrollTypeID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(MonthlyWorkPlanDA.Get(tc, fromdate, todate, payrollTypeID));
                var monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
                dr.Close();
                tc.End();
                return monthlyWorkPlans;
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        //public List<MonthlyWorkPlan> GetMonthlyDataByEmp(DateTime dAssDate, EnumWorkPlanGroup type, int nEmpID)
        //{
        //    TransactionContext tc = null;
        //    try
        //    {
        //        tc = TransactionContext.Begin();
        //        DataReader dr = new DataReader(MonthlyWorkPlanDA.GetMonthlyDataByEmp(tc, dAssDate, type, nEmpID));
        //        var monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
        //        dr.Close();
        //        tc.End();
        //        return monthlyWorkPlans;
        //    }
        //    catch (Exception e)
        //    {
        //        #region Handle Exception

        //        if (tc != null)
        //            tc.HandleError();
        //        ExceptionLog.Write(e);
        //        throw new ServiceException(e.Message, e);

        //        #endregion
        //    }
        //}

        public List<MonthlyWorkPlan> Get(int payrollTypeID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(MonthlyWorkPlanDA.Get(tc, payrollTypeID));
                var monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
                dr.Close();
                tc.End();
                return monthlyWorkPlans;
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public List<MonthlyWorkPlan> GetByPayrollTypeID(DateTime fromdate, DateTime todate, int payrolltypeID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr =
                    new DataReader(MonthlyWorkPlanDA.GetByPayrollTypeID(tc, fromdate, todate, payrolltypeID));
                var monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
                dr.Close();
                tc.End();
                return monthlyWorkPlans;
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public List<MonthlyWorkPlan> GetByDateAndPayrollType(DateTime attnDate, int payrollTypeID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(MonthlyWorkPlanDA.GetByDateAndPayrollType(tc, attnDate, payrollTypeID));
                var monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
                dr.Close();
                tc.End();
                return monthlyWorkPlans;
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public MonthlyWorkPlan GetByEmpID(int nEmpID, DateTime assDate, EnumWorkPlanGroup type)
        {
            MonthlyWorkPlan oMonthlyWorkPlan = new MonthlyWorkPlan();
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(MonthlyWorkPlanDA.GetByEmpID(tc, nEmpID, assDate, type));
                if (oreader.Read())
                {
                    oMonthlyWorkPlan = this.CreateObject<MonthlyWorkPlan>(oreader);
                }

                oreader.Close();
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oMonthlyWorkPlan;
        }

        public MonthlyWorkPlan GetByEmpID(int nEmpID, DateTime workDate)
        {
            MonthlyWorkPlan oMonthlyWorkPlan = new MonthlyWorkPlan();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(MonthlyWorkPlanDA.GetByEmpID(tc, nEmpID, workDate));
                if (oreader.Read())
                {
                    oMonthlyWorkPlan = this.CreateObject<MonthlyWorkPlan>(oreader);
                }

                oreader.Close();
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oMonthlyWorkPlan;
        }

        public List<MonthlyWorkPlan> GetMonthlyDataByEmp(DateTime fromDate, DateTime toDate, EnumWorkPlanGroup type,
            int nEmpID, int workPlanGroupID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr =
                    new DataReader(MonthlyWorkPlanDA.GetMonthlyDataByEmp(tc, fromDate, toDate, type, nEmpID,
                        workPlanGroupID));
                var monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
                dr.Close();
                tc.End();
                return monthlyWorkPlans;
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public List<MonthlyWorkPlan> GetByDate(DateTime attnDate, int payrollTypeID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(MonthlyWorkPlanDA.GetByDate(tc, attnDate, payrollTypeID));
                var monthlyWorkPlans = this.CreateObjects<MonthlyWorkPlan>(dr);
                dr.Close();
                tc.End();

                return monthlyWorkPlans;
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public DateTime GetLastSavedWorkDate(int payrollTypeID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                var lastSavedWorkDate = MonthlyWorkPlanDA.GetLastSavedWorkDate(tc, payrollTypeID);
                tc.End();

                return lastSavedWorkDate;
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public void Save(List<MonthlyWorkPlan> oMWPlans)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                var startDate = oMWPlans.Min(x => x.WorkDate);
                var endDate = oMWPlans.Max(x => x.WorkDate);

                int id = tc.GenerateID("MonthlyWorkPlan", "MonthlyWorkPlanID");

                // Delete between these Date
                MonthlyWorkPlanDA.Delete(tc, startDate, oMWPlans[0].payrollTypeID);

                // Bulk insert

                if (oMWPlans != null && oMWPlans.Count > 0)
                {
                    DataTable _monthlyWorkPlan = null;
                    _monthlyWorkPlan = new DataTable("MonthlyWorkPlan");
                    _monthlyWorkPlan.Columns.Add("MONTHLYWORKPLANID", typeof(int));
                    _monthlyWorkPlan.Columns.Add("WORKDATE", typeof(DateTime));
                    _monthlyWorkPlan.Columns.Add("SHIFTID", typeof(int));
                    _monthlyWorkPlan.Columns.Add("HOLIDAYID", typeof(int));
                    _monthlyWorkPlan.Columns.Add("CREATEDBY", typeof(int));
                    _monthlyWorkPlan.Columns.Add("CREATEDDATE", typeof(DateTime));
                    _monthlyWorkPlan.Columns.Add("MODIFIEDBY", typeof(int));
                    _monthlyWorkPlan.Columns.Add("MODIFIEDDATE", typeof(DateTime));
                    _monthlyWorkPlan.Columns.Add("TYPE", typeof(int));
                    _monthlyWorkPlan.Columns.Add("WORKPLANGROUPID", typeof(int));
                    _monthlyWorkPlan.Columns.Add("DAYSERIAL", typeof(int));
                    _monthlyWorkPlan.Columns.Add("PAYROLLTYPEID", typeof(int));
                    foreach (MonthlyWorkPlan item in oMWPlans)
                    {
                        _monthlyWorkPlan.Rows.Add(
                            item.IsNew ? id++ : item.ID,
                            item.WorkDate,
                            DataReader.GetNullValue(item.ShiftID, 0),
                            DataReader.GetNullValue(item.HolidayID, 0),
                            DataReader.GetNullValue(item.CreatedBy, 0),
                            item.CreatedDate,
                            null,
                            null,
                            (int)item.Type,
                            item.WorkPlanGroupID,
                            item.DaySerial,
                            item.payrollTypeID);
                    }

                    using (SqlBulkCopy bulkCopy = new SqlBulkCopy((SqlConnection)tc.Connection,
                        SqlBulkCopyOptions.Default, (SqlTransaction)tc.Transaction))
                    {
                        bulkCopy.BulkCopyTimeout = 600; // in seconds
                        //bulkCopy.BatchSize = 5000;
                        bulkCopy.ColumnMappings.Add("MONTHLYWORKPLANID", "MONTHLYWORKPLANID");
                        bulkCopy.ColumnMappings.Add("WORKDATE", "WORKDATE");
                        bulkCopy.ColumnMappings.Add("SHIFTID", "SHIFTID");
                        bulkCopy.ColumnMappings.Add("HOLIDAYID", "HOLIDAYID");
                        bulkCopy.ColumnMappings.Add("CREATEDBY", "CREATEDBY");
                        bulkCopy.ColumnMappings.Add("CREATEDDATE", "CREATEDDATE");
                        bulkCopy.ColumnMappings.Add("MODIFIEDBY", "MODIFIEDBY");
                        bulkCopy.ColumnMappings.Add("MODIFIEDDATE", "MODIFIEDDATE");
                        bulkCopy.ColumnMappings.Add("TYPE", "TYPE");
                        bulkCopy.ColumnMappings.Add("WORKPLANGROUPID", "WORKPLANGROUPID");
                        bulkCopy.ColumnMappings.Add("DAYSERIAL", "DAYSERIAL");
                        bulkCopy.ColumnMappings.Add("PAYROLLTYPEID", "PAYROLLTYPEID");

                        bulkCopy.DestinationTableName = "MonthlyWorkPlan";
                        bulkCopy.WriteToServer(_monthlyWorkPlan);
                    }
                }

                //foreach (MonthlyWorkPlan oMWPlan in oMWPlans)
                //{
                //    if (oMWPlan.IsNew)
                //    {
                //        int id = tc.GenerateID("MonthlyWorkPlan", "MonthlyWorkPlanID");
                //        base.SetObjectID(oMWPlan, ID.FromInteger(id));
                //        MonthlyWorkPlanDA.Insert(tc, oMWPlan);
                //    }
                //    else
                //    {
                //        MonthlyWorkPlanDA.Update(tc, oMWPlan);
                //    }

                //}
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public void UpdateShiftAndRoster(MonthlyWorkPlan oMWPlan)
        {
            TransactionContext tc = null;
            try
            {

                tc = TransactionContext.Begin(true);
                MonthlyWorkPlanDA.UpdateShiftAndRoster(tc, oMWPlan);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }


        public void DeleteOnward(DateTime fromMonth, int payrolltypeid)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                MonthlyWorkPlanDA.Delete(tc, fromMonth, payrolltypeid);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public void Delete(DateTime dFromDate, DateTime dToDate, int payrollTypeID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                MonthlyWorkPlanDA.Delete(tc, dFromDate, dToDate, payrollTypeID);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }


        //public void Delete(DateTime assignDate, string empIDs)
        //{
        //    TransactionContext tc = null;
        //    try
        //    {
        //        tc = TransactionContext.Begin(true);
        //        MonthlyWorkPlanDA.Delete(tc, assignDate, empIDs);
        //        tc.End();
        //    }
        //    catch (Exception e)
        //    {
        //        #region Handle Exception

        //        if (tc != null)
        //            tc.HandleError();
        //        ExceptionLog.Write(e);
        //        throw new ServiceException(e.Message, e);

        //        #endregion
        //    }
        //}

        public bool IsExist(DateTime dAssDate, int groupID)
        {
            bool isExist = false;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                isExist = MonthlyWorkPlanDA.IsExist(tc, dAssDate, groupID);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return isExist;
        }

        

        public List<MonthlyWorkPlan> RefreshMonthlyWorkplan(DateTime monthFromDate, DateTime monthToDate, int payrollTypeID)
        {
            List<MonthlyWorkPlan> currentMonthlyWorkPlans = new List<MonthlyWorkPlan>();
            var tempCurrentMonthlyWorkPlans = this.Get(monthFromDate, payrollTypeID);

            var PreviousMonthPlans = this.Get(monthFromDate.AddMonths(-1) , payrollTypeID);
            WorkPlanGroupService wfs = new WorkPlanGroupService();
            List<WorkPlanGroup> wfGroups = wfs.Get(EnumStatus.Regardless, payrollTypeID, string.Empty, null);
            AttnNationalHolidayService hcs = new AttnNationalHolidayService();
            List<AttnNationalHoliday> AttNHolidays = hcs.Get(EnumStatus.Regardless, payrollTypeID); 
            MonthlyWorkPlan tempMonthlyWorkPlan;
            ShiftRotationService srs = new ShiftRotationService();
            List<ShiftRotation> shiftRotations = srs.Get(EnumStatus.Regardless, payrollTypeID);

            if (monthFromDate.Day != 1) monthFromDate = GlobalFunctions.FirstDateOfMonth(monthFromDate);
            
            foreach (var currentWPGroup in wfGroups)
            {
                if (tempCurrentMonthlyWorkPlans.Any(x => x.WorkPlanGroupID == currentWPGroup.ID))
                {
                    currentMonthlyWorkPlans.AddRange(tempCurrentMonthlyWorkPlans.Where(x => x.WorkPlanGroupID== currentWPGroup.ID));
                    continue;
                }

                if (currentWPGroup.Type == EnumWorkPlanGroup.Fixed)
                {
                    for (DateTime currentDate = monthFromDate; currentDate <= monthToDate; currentDate = currentDate.AddDays(1))
                    {
                        tempMonthlyWorkPlan = new MonthlyWorkPlan
                        {
                            WorkDate = currentDate,
                            WorkPlanGroupID = currentWPGroup.ID,
                            Type = EnumWorkPlanDayType.WorkingDay,
                            HolidayID = 0,
                            payrollTypeID = payrollTypeID                         
                        };
                        tempMonthlyWorkPlan.WorkPlanGroup = currentWPGroup;
                        if (currentDate.DayOfWeek.ToHolidayDayOfWeek() == currentWPGroup.HolidayOne || currentDate.DayOfWeek.ToHolidayDayOfWeek() == currentWPGroup.HolidayTwo)
                        {
                            tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                        }

                        if (AttNHolidays.Any(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date))
                        {
                            tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.NationalHoliday;
                            tempMonthlyWorkPlan.HolidayID = AttNHolidays.First(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date).ID;
                        }

                        switch (currentDate.DayOfWeek)
                        {
                            case DayOfWeek.Sunday:
                                tempMonthlyWorkPlan.ShiftID =(int) currentWPGroup.SundayShiftID;
                                break;
                            case DayOfWeek.Monday:
                                tempMonthlyWorkPlan.ShiftID = (int)currentWPGroup.MondayShiftID;
                                break;
                            case DayOfWeek.Tuesday:
                                tempMonthlyWorkPlan.ShiftID = (int)currentWPGroup.TuesdayShiftID;
                                break;
                            case DayOfWeek.Wednesday:
                                tempMonthlyWorkPlan.ShiftID = (int)currentWPGroup.WednesdayShiftID;
                                break;
                            case DayOfWeek.Thursday:
                                tempMonthlyWorkPlan.ShiftID = (int)currentWPGroup.ThursdayShiftID;
                                break;
                            case DayOfWeek.Friday:
                                tempMonthlyWorkPlan.ShiftID = (int)currentWPGroup.FridayShiftID;
                                break;
                            case DayOfWeek.Saturday:
                                tempMonthlyWorkPlan.ShiftID = (int)currentWPGroup.SaturdayShiftID;
                                break;
                            default:
                                break;
                        }

                        currentMonthlyWorkPlans.Add(tempMonthlyWorkPlan);
                    }
                }
                else
                {
                    var lastDateofPreviousMonth = monthFromDate.AddMonths(-1).LastDateOfMonth();
                    var lastPreviousMWPlan = PreviousMonthPlans.FirstOrDefault(x => x.WorkDate.Date == lastDateofPreviousMonth && x.WorkPlanGroupID == currentWPGroup.ID);
                    var tempShiftRotations = shiftRotations.Where(x => x.WorkPlanType == currentWPGroup.Type).OrderBy(x => x.Sequence).ToList();
                    if(tempShiftRotations == null || tempShiftRotations.Count ==0)
                    {
                        throw new Exception("shift Rotation not found for the roster: " +  currentWPGroup.Name);

                    }
                    if ((currentWPGroup.Type == EnumWorkPlanGroup.Double_Shift_1 || currentWPGroup.Type == EnumWorkPlanGroup.Double_Shift_2)
                        && tempShiftRotations.Count != 2)
                    {
                        throw new Exception("There must be two roster for a double shift");
                    }
                    if ((currentWPGroup.Type == EnumWorkPlanGroup.Counter_Clock_1 || currentWPGroup.Type == EnumWorkPlanGroup.Counter_Clock_2
                        || currentWPGroup.Type == EnumWorkPlanGroup.Counter_Clock_3) && tempShiftRotations.Count != 3)
                    {
                        throw new Exception("There must be three roster for a Counter-Clock-shift");
                    }

                    int DaySerial = 1;
                    int shiftID = currentWPGroup.InitialShiftID;

                    if (lastPreviousMWPlan != null)
                    {
                        lastPreviousMWPlan.WorkPlanGroup = currentWPGroup;
                        DaySerial = lastPreviousMWPlan.NextDaySerial;
                        shiftID = lastPreviousMWPlan.ShiftID;
                        if (DaySerial == 1)
                        {
                            var lastRotationShift = tempShiftRotations.FirstOrDefault(x => x.ShiftID == lastPreviousMWPlan.ShiftID);
                            shiftID = lastRotationShift.NextShiftID(tempShiftRotations);
                        }
                    }
                    tempMonthlyWorkPlan = new MonthlyWorkPlan();
                    for (DateTime currentDate = monthFromDate; currentDate <= monthToDate; currentDate = currentDate.AddDays(1))
                    {

                        tempMonthlyWorkPlan = new MonthlyWorkPlan
                        {
                            WorkDate = currentDate,
                            WorkPlanGroupID = currentWPGroup.ID,
                            ShiftID = shiftID,
                            Type = EnumWorkPlanDayType.WorkingDay,
                            HolidayID = 0,
                            DaySerial = DaySerial,
                            WorkPlanGroup= currentWPGroup
                        };

                        if (currentDate.DayOfWeek.ToHolidayDayOfWeek() == currentWPGroup.HolidayOne || 
                            currentDate.DayOfWeek.ToHolidayDayOfWeek() == currentWPGroup.HolidayTwo)
                        {
                            tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                        }
                        else if (DaySerial == 6 && currentWPGroup.HasTwoHolidays && currentWPGroup.HolidayOne == HolidayDayOfWeek.Auto)
                        {
                            tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                        }
                        else if (DaySerial == 7 && currentWPGroup.HasTwoHolidays && currentWPGroup.HolidayTwo == HolidayDayOfWeek.Auto)
                        {
                            tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                        }
                        else if (DaySerial == 7 && !currentWPGroup.HasTwoHolidays && currentWPGroup.HolidayOne == HolidayDayOfWeek.Auto)
                        {
                            tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                        }

                        if (AttNHolidays.Any(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date))
                        {
                            tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.NationalHoliday;
                            tempMonthlyWorkPlan.HolidayID = AttNHolidays.First(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date).ID;
                        }


                        currentMonthlyWorkPlans.Add(tempMonthlyWorkPlan);

                        if (tempMonthlyWorkPlan.Type == EnumWorkPlanDayType.WeeklyHoliday && DaySerial != 7)
                            tempMonthlyWorkPlan.DaySerial = 7;


                        if (tempMonthlyWorkPlan.WorkPlanGroup.Type == EnumWorkPlanGroup.Two_Days_Shift_1 &&
                            tempMonthlyWorkPlan.Type == EnumWorkPlanDayType.WeeklyHoliday && DaySerial != 2)
                            continue;

                        if (tempMonthlyWorkPlan.WorkPlanGroup.Type == EnumWorkPlanGroup.Three_Days_Shift_1 &&
                            tempMonthlyWorkPlan.Type == EnumWorkPlanDayType.WeeklyHoliday && DaySerial != 3)
                            continue;

                        DaySerial = tempMonthlyWorkPlan.NextDaySerial;
                        if (DaySerial == 1)
                        {
                            var lastRotationShift = tempShiftRotations.FirstOrDefault(x => x.ShiftID == shiftID);
                            shiftID = lastRotationShift.NextShiftID(tempShiftRotations);
                        }
                    }
                }

            }

            return currentMonthlyWorkPlans;
            // lblStatus.Text = _currentMonthlyWorkPlans.All(o => o.ID.IsUnassigned) ? "UnSaved Data" : "Saved Data";
        }
        public void SetWorkDayType(MonthlyWorkPlan newPlan, List<AttnNationalHoliday> AttNHolidays , int DaySerial, DateTime currentDate, WorkPlanGroup currentWPGroup)
        {
            EnumWorkPlanDayType rtype = EnumWorkPlanDayType.WorkingDay;
            if (currentDate.DayOfWeek.ToHolidayDayOfWeek() == currentWPGroup.HolidayOne || currentDate.DayOfWeek.ToHolidayDayOfWeek() == currentWPGroup.HolidayTwo)
            {
                newPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
            }
            else if (DaySerial == 6 && currentWPGroup.HasTwoHolidays && currentWPGroup.HolidayOne == HolidayDayOfWeek.Auto)
            {
                newPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
            }
            else if (DaySerial == 7 && currentWPGroup.HasTwoHolidays && currentWPGroup.HolidayTwo == HolidayDayOfWeek.Auto)
            {
                newPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
            }
            else if (DaySerial == 7 && !currentWPGroup.HasTwoHolidays && currentWPGroup.HolidayOne == HolidayDayOfWeek.Auto)
            {
                newPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
            }

            if (AttNHolidays.Any(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date))
            {
                newPlan.Type = EnumWorkPlanDayType.NationalHoliday;
                newPlan.HolidayID = AttNHolidays.First(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date).ID;
            }


        }
        public List<MonthlyWorkPlan> updateWorkPlan(MonthlyWorkPlan mplan)
        {

            List<AttnNationalHoliday> AttNHolidays = new AttnNationalHolidayService().Get(EnumStatus.Regardless, mplan.payrollTypeID);
            var monthToDate = mplan.WorkDate.LastDateOfMonth();
            DateTime dDate = mplan.WorkDate.AddDays(1);
            int DaySerial = 1;
            List<ShiftRotation> shiftRotation = new ShiftRotationService().Get(EnumStatus.Active, mplan.payrollTypeID);
            mplan.WorkPlanGroup = new WorkPlanGroupService().Get((int)mplan.WorkPlanGroupID);
            var tempShiftRotations = shiftRotation.Where(x => x.WorkPlanType == mplan.WorkPlanGroup.Type).OrderBy(x => x.Sequence).ToList();
            int shiftID = mplan.ShiftID;
            List<MonthlyWorkPlan> mplans = new List<MonthlyWorkPlan>();
            mplans.Add(mplan);
            List<Shift> oshifts = new ShiftService().Get(string.Empty, string.Empty, EnumStatus.Regardless, mplan.payrollTypeID);
            
            this.SetWorkDayType(mplan, AttNHolidays, 1, mplan.WorkDate, mplan.WorkPlanGroup);

            if (mplan.Type == EnumWorkPlanDayType.WorkingDay)
                DaySerial = 2;
            if (mplan.WorkPlanGroup.Type == EnumWorkPlanGroup.Fixed)
            {

                for (DateTime currentDate = dDate; currentDate <= monthToDate; currentDate = currentDate.AddDays(1))
                {
                    MonthlyWorkPlan tempMonthlyWorkPlan = new MonthlyWorkPlan
                    {
                        WorkDate = currentDate,
                        WorkPlanGroupID = mplan.WorkPlanGroup.ID,
                        Type = EnumWorkPlanDayType.WorkingDay,
                        HolidayID = 0,
                        payrollTypeID = mplan.payrollTypeID

                    };

                    if (currentDate.DayOfWeek.ToHolidayDayOfWeek() == mplan.WorkPlanGroup.HolidayOne || currentDate.DayOfWeek.ToHolidayDayOfWeek() == mplan.WorkPlanGroup.HolidayTwo)
                    {
                        tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                    }

                    if (AttNHolidays.Any(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date))
                    {
                        tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.NationalHoliday;
                        tempMonthlyWorkPlan.HolidayID = AttNHolidays.First(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date).ID;
                    }

                    switch (currentDate.DayOfWeek)
                    {
                        case DayOfWeek.Sunday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.SundayShiftID;
                            break;
                        case DayOfWeek.Monday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.MondayShiftID;
                            break;
                        case DayOfWeek.Tuesday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.TuesdayShiftID;
                            break;
                        case DayOfWeek.Wednesday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.WednesdayShiftID;
                            break;
                        case DayOfWeek.Thursday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.ThursdayShiftID;
                            break;
                        case DayOfWeek.Friday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.FridayShiftID;
                            break;
                        case DayOfWeek.Saturday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.SaturdayShiftID;
                            break;
                        default:
                            break;
                    }

                    mplans.Add(tempMonthlyWorkPlan);
                }
            }
            else
            {
                for (DateTime currentDate = dDate; currentDate <= monthToDate; currentDate = currentDate.AddDays(1))
                {

                    MonthlyWorkPlan newPlan = new MonthlyWorkPlan();
                    newPlan.WorkDate = currentDate;
                    newPlan.WorkPlanGroupID = mplan.WorkPlanGroupID;
                    newPlan.payrollTypeID = mplan.payrollTypeID;
                    newPlan.WorkPlanGroup = mplan.WorkPlanGroup;

                    newPlan.DaySerial = DaySerial;
                    newPlan.Type = EnumWorkPlanDayType.WorkingDay;

                    //if (DaySerial == 7)
                    //    newPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                    //if (AttNHolidays.Any(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date))
                    //{
                    //    newPlan.Type = EnumWorkPlanDayType.NationalHoliday;
                    //    newPlan.HolidayID = AttNHolidays.First(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date).ID;
                    //}
                    this.SetWorkDayType(newPlan, AttNHolidays, DaySerial, newPlan.WorkDate, mplan.WorkPlanGroup);
                    if (DaySerial == 1)
                    {
                        var lastRotationShift = tempShiftRotations.FirstOrDefault(x => x.ShiftID == shiftID);
                        shiftID = lastRotationShift.NextShiftID(tempShiftRotations);
                    }

                    DaySerial = newPlan.NextDaySerial;
                    Shift oshif = oshifts.FirstOrDefault(x => x.ID == shiftID);
                    newPlan.ShiftID = oshif.ID;
                    mplans.Add(newPlan);
                }
            }
        
            return mplans;
        }

        public List<MonthlyWorkPlan> updateWorkPlanSingleDay(MonthlyWorkPlan mplan)
        {

            List<AttnNationalHoliday> AttNHolidays = new AttnNationalHolidayService().Get(EnumStatus.Regardless, mplan.payrollTypeID);
            var monthToDate = mplan.WorkDate.LastDateOfMonth();
            DateTime dDate = mplan.WorkDate.AddDays(1);
            int DaySerial = 1;
            List<ShiftRotation> shiftRotation = new ShiftRotationService().Get(EnumStatus.Active, mplan.payrollTypeID);
            mplan.WorkPlanGroup = new WorkPlanGroupService().Get((int)mplan.WorkPlanGroupID);
            var tempShiftRotations = shiftRotation.Where(x => x.WorkPlanType == mplan.WorkPlanGroup.Type).OrderBy(x => x.Sequence).ToList();
            int shiftID = mplan.ShiftID;
            List<MonthlyWorkPlan> mplans = new List<MonthlyWorkPlan>();
            mplans.Add(mplan);
            List<Shift> oshifts = new ShiftService().Get(string.Empty, string.Empty, EnumStatus.Regardless, mplan.payrollTypeID);

            this.SetWorkDayType(mplan, AttNHolidays, 1, mplan.WorkDate, mplan.WorkPlanGroup);

            if (mplan.Type == EnumWorkPlanDayType.WorkingDay)
                DaySerial = 2;
            if (mplan.WorkPlanGroup.Type == EnumWorkPlanGroup.Fixed)
            {

                for (DateTime currentDate = dDate; currentDate <= monthToDate; currentDate = currentDate.AddDays(1))
                {
                    MonthlyWorkPlan tempMonthlyWorkPlan = new MonthlyWorkPlan
                    {
                        WorkDate = currentDate,
                        WorkPlanGroupID = mplan.WorkPlanGroup.ID,
                        Type = EnumWorkPlanDayType.WorkingDay,
                        HolidayID = 0,
                        payrollTypeID = mplan.payrollTypeID

                    };

                    if (currentDate.DayOfWeek.ToHolidayDayOfWeek() == mplan.WorkPlanGroup.HolidayOne || currentDate.DayOfWeek.ToHolidayDayOfWeek() == mplan.WorkPlanGroup.HolidayTwo)
                    {
                        tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                    }

                    if (AttNHolidays.Any(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date))
                    {
                        tempMonthlyWorkPlan.Type = EnumWorkPlanDayType.NationalHoliday;
                        tempMonthlyWorkPlan.HolidayID = AttNHolidays.First(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date).ID;
                    }

                    switch (currentDate.DayOfWeek)
                    {
                        case DayOfWeek.Sunday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.SundayShiftID;
                            break;
                        case DayOfWeek.Monday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.MondayShiftID;
                            break;
                        case DayOfWeek.Tuesday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.TuesdayShiftID;
                            break;
                        case DayOfWeek.Wednesday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.WednesdayShiftID;
                            break;
                        case DayOfWeek.Thursday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.ThursdayShiftID;
                            break;
                        case DayOfWeek.Friday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.FridayShiftID;
                            break;
                        case DayOfWeek.Saturday:
                            tempMonthlyWorkPlan.ShiftID = (int)mplan.WorkPlanGroup.SaturdayShiftID;
                            break;
                        default:
                            break;
                    }

                    mplans.Add(tempMonthlyWorkPlan);
                }
            }
            else
            {
                for (DateTime currentDate = dDate; currentDate <= monthToDate; currentDate = currentDate.AddDays(1))
                {

                    MonthlyWorkPlan newPlan = new MonthlyWorkPlan();
                    newPlan.WorkDate = currentDate;
                    newPlan.WorkPlanGroupID = mplan.WorkPlanGroupID;
                    newPlan.payrollTypeID = mplan.payrollTypeID;


                    newPlan.DaySerial = DaySerial;
                    newPlan.Type = EnumWorkPlanDayType.WorkingDay;

                    //if (DaySerial == 7)
                    //    newPlan.Type = EnumWorkPlanDayType.WeeklyHoliday;
                    //if (AttNHolidays.Any(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date))
                    //{
                    //    newPlan.Type = EnumWorkPlanDayType.NationalHoliday;
                    //    newPlan.HolidayID = AttNHolidays.First(x => currentDate.Date >= x.FromDate.Date && currentDate.Date <= x.ToDate.Date).ID;
                    //}
                    this.SetWorkDayType(newPlan, AttNHolidays, DaySerial, newPlan.WorkDate, mplan.WorkPlanGroup);
                    if (DaySerial == 1)
                    {
                        var lastRotationShift = tempShiftRotations.FirstOrDefault(x => x.ShiftID == shiftID);
                        shiftID = lastRotationShift.NextShiftID(tempShiftRotations);
                    }

                    DaySerial = newPlan.NextDaySerial;
                    Shift oshif = oshifts.FirstOrDefault(x => x.ID == shiftID);
                    newPlan.ShiftID = oshif.ID;
                    mplans.Add(newPlan);
                }
            }

            return mplans;
        }

        #endregion
    }

    #endregion
}