using HRM.BO;
using Ease.Core.DataAccess;
using Ease.Core.Model;
using Ease.Core.Utility;
using System;
using System.Collections.Generic;

namespace HRM.DA
{
    #region TermParameter Service

    public class TermParameterService : ServiceTemplate, ITermParameterService
    {
        #region Private functions and declaration

        #endregion

        public TermParameterService()
        {
        }

        private void MapObject(TermParameter oTermParameter, DataReader oReader)
        {
            base.SetObjectID(oTermParameter, oReader.GetInt32("TermParameterID").Value);
            oTermParameter.TermID = oReader.GetString("termID") == null ? 0 : oReader.GetInt32("termID").Value;
            oTermParameter.EffectDate = oReader.GetDateTime("effectDate").Value;
            oTermParameter.Amount = oReader.GetDouble("amount").Value;
            oTermParameter.Type = (EnumOverTimeType)oReader.GetInt32("type").Value;
            oTermParameter.CreatedBy = oReader.GetString("CreatedBy") == null ? 0 : oReader.GetInt32("CreatedBy").Value;
            oTermParameter.CreatedDate = oReader.GetDateTime("CreationDate").Value;
            //oTermParameter.housInMonth = oReader.GetInt32("housInMonth").Value;
            oTermParameter.housInMonth = oReader.GetInt32("housInMonth", 0);
            oTermParameter.ModifiedBy =
                oReader.GetString("ModifiedBy") == null ? 0 : oReader.GetInt32("ModifiedBy").Value;
            oTermParameter.ModifiedDate = oReader.GetDateTime("ModifiedDate");
            this.SetObjectState(oTermParameter, Ease.Core.ObjectState.Saved);
        }

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

        protected TermParameter CreateObject(DataReader oReader)
        {
            TermParameter oTermParameter = new TermParameter();
            MapObject(oTermParameter, oReader);
            return oTermParameter;
        }

        private void MapObjectForTEGrade(TermParameter.TermEntityGrade oTermEGrade, DataReader oReader)
        {
            base.SetObjectID(oTermEGrade, oReader.GetInt32("TermentityID").Value);
            oTermEGrade.TermEntityID =
                oReader.GetString("TermentityID") == null ? 0 : oReader.GetInt32("TermentityID").Value;
            oTermEGrade.GradeID = oReader.GetString("GRADEID") == null ? 0 : oReader.GetInt32("GRADEID").Value;
            this.SetObjectState(oTermEGrade, Ease.Core.ObjectState.Saved);
        }
        //protected override T CreateObject1<T>(DataReader oReader)
        //{
        //    TermEntityGrade oTermEGrade = new TermEntityGrade();
        //    MapObjectForTEGrade(oTermEGrade, oReader);
        //    return oTermEGrade as T;
        //}

        protected TermParameter.TermEntityGrade CreateObjectForTEGrade(DataReader oReader)
        {
            TermParameter.TermEntityGrade oTermEGrade = new TermParameter.TermEntityGrade();
            MapObjectForTEGrade(oTermEGrade, oReader);
            return oTermEGrade;
        }

        private List<TermParameter.TermEntityGrade> FillChildren(DataReader dr)
        {
            List<TermParameter.TermEntityGrade> _TerEGrades = new List<TermParameter.TermEntityGrade>();
            while (dr.Read())
            {
                TermParameter.TermEntityGrade item = this.CreateObjectForTEGrade(dr);
                _TerEGrades.Add(item);
            }

            return _TerEGrades;
        }

        #region Service implementation

        public TermParameter Get(int id)
        {
            TermParameter oTermParameter = new TermParameter();
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(TermParameterDA.Get(tc, id));
                if (oreader.Read())
                {
                    oTermParameter = this.CreateObject<TermParameter>(oreader);
                }

                oreader.Close();

                if (oTermParameter != null)
                {
                    DataReader ord = new DataReader(TermParameterDA.GetGrades(tc, id));
                    oTermParameter.TermEntityGrades = this.FillChildren(ord);
                    ord.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 oTermParameter;
        }
        
        public List<TermParameter> Get(bool IncludeChildren, int payrolltypeId)
        {
            List<TermParameter> termParams = new List<TermParameter>();
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();

                DataReader dr = new DataReader(TermParameterDA.GetByPayrollTypeID(tc, payrolltypeId));
                termParams = this.CreateObjects<TermParameter>(dr);

                dr.Close();

                if (IncludeChildren)
                {
                    SetupDetailService sdService = new SetupDetailService();
                    foreach (TermParameter item in termParams)
                    {
                        item.SetupDetails = sdService.GetParametersById(EnumParameterSetup.OT, item.ID);
                    }
                }
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);

                throw new ServiceException(e.Message, e);

                #endregion
            }

            return termParams;
        }

        public List<TermParameter.TermEntityGrade> GetUsedGrades(int termID)
        {
            List<TermParameter.TermEntityGrade> usedGrades = new List<TermParameter.TermEntityGrade>();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();

                DataReader dr = new DataReader(TermParameterDA.GetUsedGrades(tc, termID));
                usedGrades = this.FillChildren(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 usedGrades;
        }

        //public List<EmployeeSetupParameter> ApplicableParameters(int gradeID)
        //{
        //    EmployeeSetupParameter empParameter = new EmployeeSetupParameter(EnumParameterSetup.OT);
        //    empParameter.Employee = employee;
        //    empParameter.ParameterIDs = SetupManager.ApplicableParameters(employee, EnumParameterSetup.OT);
        //    return empParameter;
        //}

        //public List<EmployeeSetupParameter> ApplicableParameters(List<Employee> employees)
        //{
        //    List<SetupDetail> details = new SetupDetailService().GetParameters(EnumParameterSetup.OT);
        //    List<EnmSetupManagerTranType> types = new SetupDetailService().GetTypes(EnumParameterSetup.OT);
        //    List<EmployeeSetupParameter> empParametes = new List<EmployeeSetupParameter>();
        //    foreach (Employee emp in employees)
        //    {
        //        EmployeeSetupParameter empparameter = new EmployeeSetupParameter(EnumParameterSetup.OT);
        //        empparameter.Employee = emp;
        //        empparameter.ParameterIDs = SetupManager.ApplicableParameters(emp, EnumParameterSetup.OT, types, details);
        //        empParametes.Add(empparameter);
        //    }
        //    return empParametes;
        //}

        public List<TermParameter> GetByPayrollTypeID(int payrollTypeID)
        {
            List<TermParameter> termParams = new List<TermParameter>();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();

                DataReader dr = new DataReader(TermParameterDA.GetByPayrollTypeID(tc, payrollTypeID));
                termParams = this.CreateObjects<TermParameter>(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 termParams;
        }


        public List<TermParameter> GetwithDetail(int payrollTypeID)
        {
            List<TermParameter> termParams = new List<TermParameter>(); 

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();

                DataReader dr = new DataReader(TermParameterDA.GetByPayrollTypeID(tc, payrollTypeID));
                termParams = this.CreateObjects<TermParameter>(dr);
                dr.Close();
                
                if(termParams !=null)
                {
                    dr = new DataReader(TermParameterDA.GetGrades(tc));
                    List<TermParameter.TermEntityGrade> grs = FillChildren(dr);
                    termParams.ForEach(x =>
                    {
                        x.TermEntityGrades = grs.FindAll(y => y.TermEntityID == x.ID);
                    });
                    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 termParams;
        }

        public List<TermParameter> GetByGradeID(int nGradeID)
        {
            List<TermParameter> termParams = new List<TermParameter>();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();

                DataReader dr = new DataReader(TermParameterDA.GetByGradeID(tc, nGradeID));
                termParams = this.CreateObjects<TermParameter>(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 termParams;
        }

        public List<TermParameter.TermEntityGrade> GetGrades(int nID)
        {
            List<TermParameter.TermEntityGrade> termEntityGrades = new List<TermParameter.TermEntityGrade>();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();

                DataReader dr = new DataReader(TermParameterDA.GetGrades(tc, nID));
                termEntityGrades = FillChildren(dr);
                //termEntityGrades = this.CreateObjects<TermEntityGrade>(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 termEntityGrades;
        }

        public int Save(TermParameter oTermParameter)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                if (oTermParameter.IsNew)
                {
                    int id = tc.GenerateID("TermParameter", "TermParameterID");
                    base.SetObjectID(oTermParameter, id);
                    TermParameterDA.Insert(tc, oTermParameter);
                }
                else
                {
                    TermParameterDA.Update(tc, oTermParameter);
                    TermParameterDA.DeleteGrade(tc, oTermParameter.ID);
                }


                foreach (TermParameter.TermEntityGrade teGrade in oTermParameter.TermEntityGrades)
                {
                    teGrade.TermEntityID = oTermParameter.ID;
                    TermParameterDA.Insert(tc, teGrade);
                }

                //SetupDetailService sdetailService = new SetupDetailService();
                //sdetailService.Insert(tc, EnumParameterSetup.OT, 
                //    oTermParameter.SetupDetails, oTermParameter.ID);

                tc.End();
                return oTermParameter.ID;
            }
            catch (Exception e)
            {
                #region Handle Exception

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

                #endregion
            }
        }

        public void Delete(int id)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                SetupDetailService sd = new SetupDetailService();
                sd.Delete(tc, EnumParameterSetup.OT, id);

                TermParameterDA.Delete(tc, id);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

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

                #endregion
            }
        }

        #endregion

        public double ConvertToHourlyRate(double nBasic, double hourlyPercent = 100)
        {
            double amount = 0;
            nBasic = Math.Round(nBasic);
            int hours = ConfigurationManager.GetIntValue("overtime", "hoursonmonth", EnumConfigurationType.Logic);
            if (hours <= 0) hours = 208;
            double doubleHOur = Convert.ToDouble(hours);
            amount = (nBasic / doubleHOur) * (hourlyPercent / 100.00);
            return Math.Round(amount, 2);

        }
    }

    #endregion
}