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

namespace HRM.DA
{
    #region Leave Service

    public class LeaveService : ServiceTemplate, ILeaveService
    {
        #region Private functions and declaration

        public LeaveService()
        {
        }

        private void MapObject(Leave oLeave, DataReader oReader)
        {
            base.SetObjectID(oLeave, oReader.GetInt32("LeaveID").Value);
            oLeave.Code = oReader.GetString("Code");
            oLeave.Description = oReader.GetString("Description");
            oLeave.DescriptionInBangla = oReader.GetString("DescriptionInBangla", true, null);
            oLeave.RemarksNeeded = oReader.GetBoolean("RemarksNeeded").Value;
            oLeave.ApplicableFor = (EnumGender)oReader.GetInt32("ApplicableFor").Value;
            oLeave.IsBalanceCalculationNeeded = oReader.GetBoolean("IsBalanceCalRequired").Value;
            oLeave.AutoLeaveReason = oReader.GetBoolean("AutoLeaveReason").Value;
            oLeave.Status = (EnumStatus)oReader.GetInt32("Status").Value;
            oLeave.IsEarnedLeave = oReader.GetBoolean("IsEarnedLeave").Value;
            oLeave.Sequence = oReader.GetInt32("SequenceNo").Value;
            oLeave.CreatedBy = oReader.GetString("CreatedBy") == null ? 0 : oReader.GetInt32("CreatedBy").Value;
            oLeave.CreatedDate = oReader.GetDateTime("CreatedDate").Value;
            oLeave.ModifiedBy = oReader.GetString("ModifiedBy") == null ? 0 : oReader.GetInt32("ModifiedBy").Value;
            ;
            oLeave.ModifiedDate = oReader.GetDateTime("ModifiedDate");
            oLeave.IsHalfDayLeave = oReader.GetBoolean("IsHalfDayLeave").Value;
            oLeave.IsAttachmentNeeded = oReader.GetBoolean("IsAttachmentNeeded").HasValue
                ? oReader.GetBoolean("IsAttachmentNeeded").Value
                : false;
            oLeave.PayrollTypeID =
                oReader.GetString("payrollTypeID") == null ? 0 : oReader.GetInt32("payrollTypeID").Value;
            oLeave.AttachmentMaxDays =
                oReader.GetString("AttachmentMaxDays") == null ? 0 : oReader.GetInt32("AttachmentMaxDays").Value;
            oLeave.AttachmentMaxDays =
                oReader.GetString("AttachmentMaxDays") == null ? 0 : oReader.GetInt32("AttachmentMaxDays").Value;
            oLeave.IsLFA = oReader.GetBoolean("IsLFA").HasValue
                ? oReader.GetBoolean("IsLFA").Value
                : false;
            oLeave.LfaMaxDays =
                oReader.GetString("LfaMaxDays") == null ? 0 : oReader.GetInt32("LfaMaxDays").Value;
            oLeave.AllowNegativeBalance = oReader.GetBoolean("AllowNegativeBalance").HasValue
                ? oReader.GetBoolean("AllowNegativeBalance").Value
                : false;
            oLeave.MaxConsequentDays =
                oReader.GetString("MaxConsequentDays") == null ? 0 : oReader.GetInt32("MaxConsequentDays").Value;
            oLeave.IsCompensatoryLeave = oReader.GetBoolean("IsCompensatoryLeave").Value;
            oLeave.IsPreApproval = oReader.GetBoolean("IsPreApproval").HasValue
                ? oReader.GetBoolean("IsPreApproval").Value
                : false;
            oLeave.PreApprovalDays =
                oReader.GetString("PreApprovalDays") == null ? 0 : oReader.GetInt32("PreApprovalDays").Value;
            oLeave.IsSelfCancellation = oReader.GetBoolean("IsSelfCancellation").HasValue
                ? oReader.GetBoolean("IsSelfCancellation").Value
                : false;
            oLeave.SelfCancellationDays =
                oReader.GetString("SelfCancellationDays") == null ? 0 : oReader.GetInt32("SelfCancellationDays").Value;

            oLeave.CancelOnApprovalLeaveEntry = oReader.GetBoolean("CancelOnApprovalLeaveEntry", false);
            oLeave.HasMinimumDays = oReader.GetBoolean("HasMinimumDays", true, false);
            oLeave.MinimumDays = oReader.GetInt32("MinimumDays", true, 0);
            oLeave.BalanceRoundofDigit = oReader.GetInt32("BalanceRoundofDigit", true, 1);
            this.SetObjectState(oLeave, Ease.Core.ObjectState.Saved);
            //this.SetObjectState(oLeave, ObjectState.Saved);
        }

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

        private Leave CreateObject(DataReader oReader)
        {
            Leave oLeave = new Leave();
            MapObject(oLeave, oReader);
            return oLeave;
        }

        #endregion

        #region Service implementation

        public Leave Get(int id)
        {
            Leave oLeave = new Leave();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(LeaveDA.Get(tc, id));
                if (oreader.Read())
                {
                    oLeave = this.CreateObject<Leave>(oreader);
                }

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

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException("Failed to Get Leave", e);

                #endregion
            }

            return oLeave;
        }

        //public Leave GetIDByName(string sLeave, int payrollTypeID)
        //{
        //    Leave oLeave = new Leave();

        //    TransactionContext tc = null;
        //    try
        //    {
        //        tc = TransactionContext.Begin();
        //        DataReader oreader = new DataReader(LeaveDA.GetIDByName(tc, sLeave, payrollTypeID));
        //        if (oreader.Read())
        //        {
        //            oLeave = this.CreateObject<Leave>(oreader);
        //        }
        //        oreader.Close();
        //        tc.End();
        //    }
        //    catch (Exception e)
        //    {
        //        #region Handle Exception
        //        if (tc != null)
        //            tc.HandleError();
        //        ExceptionLog.Write(e);
        //        throw new ServiceException("Failed to Get Leave", e);
        //        #endregion
        //    }

        //    return oLeave;
        //}
        //public Leave GetIDByCode(string sLeave, int payrollTypeID)
        //{
        //    Leave oLeave = new Leave();

        //    TransactionContext tc = null;
        //    try
        //    {
        //        tc = TransactionContext.Begin();
        //        DataReader oreader = new DataReader(LeaveDA.GetIDByCode(tc, sLeave, payrollTypeID));
        //        if (oreader.Read())
        //        {
        //            oLeave = this.CreateObject<Leave>(oreader);
        //        }
        //        oreader.Close();
        //        tc.End();
        //    }
        //    catch (Exception e)
        //    {
        //        #region Handle Exception
        //        if (tc != null)
        //            tc.HandleError();
        //        ExceptionLog.Write(e);
        //        throw new ServiceException("Failed to Get Leave", e);
        //        #endregion
        //    }

        //    return oLeave;
        //}


        public List<Leave> GetAll()
        {
            List<Leave> oLeaves = new List<Leave>();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(LeaveDA.GetAll(tc));
                oLeaves = this.CreateObjects<Leave>(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 oLeaves;
        }

        
        public List<Leave> getEmpApplicableLeave(int employeeid)
        {
            
            List<Leave> leaves = new List<Leave>();
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(LeaveDA.GetEmpApplicableLeave(tc, employeeid));
                leaves = this.CreateObjects<Leave>(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 leaves;
        }

        public List<Leave> Get(EnumStatus status, string code, string name, int payrollTypeID)
        {
            List<Leave> leaves = new List<Leave>();
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(LeaveDA.Get(tc, status, code, name, payrollTypeID));
                leaves = this.CreateObjects<Leave>(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 leaves;
        }

        public List<Leave> Get(EnumStatus status, int payrollTypeID)
        {
            List<Leave> leaves = new List<Leave>();
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(LeaveDA.Get(tc, status, String.Empty, String.Empty, payrollTypeID));
                leaves = this.CreateObjects<Leave>(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 leaves;
        }

        public List<Leave> Get()
        {
            List<Leave> leaves = new List<Leave>();
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(LeaveDA.Get(tc));
                leaves = this.CreateObjects<Leave>(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 leaves;
        }

        public int Save(Leave oLeave)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                if (oLeave.IsNew)
                {
                    int id = tc.GenerateID("Leave", "LeaveID");
                    base.SetObjectID(oLeave, id);
                    int seqNo = tc.GenerateID("Leave", "SequenceNO");
                    oLeave.Sequence = seqNo;
                    LeaveDA.Insert(tc, oLeave);
                }
                else
                {
                    LeaveDA.Update(tc, oLeave);
                }

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

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                //throw new ServiceException("Failed to Get Leave", e);
                throw new Exception("Failed to Insert Leave. Because " + e.Message, e);

                #endregion
            }
        }

        public void Delete(int id, int payrollTypeID)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                LeaveDA.Delete(tc, id, 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 List<Leave> GetLeaves(int payrollTypeID)
        {
            List<Leave> leaves = new List<Leave>();

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

                DataReader dr = new DataReader(LeaveDA.GetLeaves(tc, payrollTypeID));
                leaves = this.CreateObjects<Leave>(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 leaves;
        }

        public string Get(DateTime fromDate, DateTime toDate)
        {
            string str = (toDate.Day - fromDate.Day + 1).ToString();
            return str;
        }

        public bool IsAttachmentAplicable(Leave leave, decimal totalDays)
        {
            //if (totalDays > 3 && (leave.Code.ToLower() == "sl" || leave.Code.ToLower() == "ml") && leave.IsAttachmentNeeded)
            if ((leave.Code.Trim().ToLower().Contains("sl".ToString()) ||
                 leave.Code.Trim().ToLower().Contains("ml".ToString())) &&
                 leave.IsAttachmentNeeded && totalDays >= leave.AttachmentMaxDays)
            {
                return true;
            }
            else
                return false;
        }
        #endregion
    }

    #endregion
}