using System;
using System.Data;
using System.Linq;
using Ease.CoreV35;
using Ease.CoreV35.DataAccess;
using System.Collections.Generic;
using Payroll.BO;
using Ease.Core.Model;
using HRM.BO;
using Ease.Core.DataAccess;
using Ease.Core.Utility;
using HRM.DA;
using static iTextSharp.text.pdf.AcroFields;
using System.Data.Common;
using iTextSharp.text;
using System.Text;

namespace Payroll.Service
{
    #region ClaimBasic Service
    public class PRBCalculationService : ServiceTemplate, IPRBCalculationService
    {
        public PRBCalculationService() { }

        private void MapObject(PRBCalculation oPRBCalculation, DataReader oReader)
        {
            base.SetObjectID(oPRBCalculation, oReader.GetInt32("PRBCalculationID").Value);
            oPRBCalculation.EmployeeID = (int)oReader.GetInt32("EmployeeID");
            oPRBCalculation.NoOFDays = (int)oReader.GetInt32("NoOFDays");
            oPRBCalculation.BonusAmount = oReader.GetDouble("BonusAmount");
            oPRBCalculation.TargetT1 = oReader.GetDouble("TargetT1", 0);
            oPRBCalculation.AcheiveT1 = oReader.GetDouble("AcheiveT1", 0);
            oPRBCalculation.AmountT1 = oReader.GetDouble("AmountT1", 0);
            oPRBCalculation.TargetT2 = oReader.GetDouble("TargetT2", 0);
            oPRBCalculation.AcheiveT2 = oReader.GetDouble("AcheiveT2", 0);
            oPRBCalculation.AmountT2 = oReader.GetDouble("AmountT2", 0);
            oPRBCalculation.TargetT3 = oReader.GetDouble("TargetT3", 0);
            oPRBCalculation.AcheiveT3 = oReader.GetDouble("AcheiveT3", 0);
            oPRBCalculation.AmountT3 = oReader.GetDouble("AmountT3", 0);
            oPRBCalculation.TargetT4 = oReader.GetDouble("TargetT4", 0);
            oPRBCalculation.AcheiveT4 = oReader.GetDouble("AcheiveT4", 0);
            oPRBCalculation.AmountT4 = oReader.GetDouble("AmountT4", 0);
            oPRBCalculation.TargetT5 = oReader.GetDouble("TargetT5", 0);
            oPRBCalculation.AcheiveT5 = oReader.GetDouble("AcheiveT5", 0);
            oPRBCalculation.AmountT5 = oReader.GetDouble("AmountT5", 0);
            oPRBCalculation.TotalAcheive = oReader.GetDouble("TotalAcheive",0);
            oPRBCalculation.TotalPRB = oReader.GetDouble("TotalPRB",0);
            oPRBCalculation.Tax = oReader.GetDouble("Tax",0);
            oPRBCalculation.NetAmount = oReader.GetDouble("NetAmount",0);
            oPRBCalculation.AnnualBasicSalary = oReader.GetDouble("AnnualBaseSalary", 0);
            oPRBCalculation.CreatedBy = oReader.GetInt32("CreatedBy").Value;
            //oPRBCalculation.ModifiedBy = oReader.GetInt32("ModifiedBy");
            oPRBCalculation.CreatedDate = oReader.GetDateTime("CreatedDate").Value;
            oPRBCalculation.EndDate = oReader.GetDateTime("PRBMonth").Value;
            oPRBCalculation.Year = oReader.GetDateTime("PRBYear").Value;
            oPRBCalculation.BatchID = (int)oReader.GetInt32("BatchID",true,0);
            oPRBCalculation.PRBStatus = (EnumPRBStatus)oReader.GetInt32("PRBStatus", true, 0);
            //oPRBCalculation.ModifiedDate = oReader.GetDateTime("ModifiedDate");

            this.SetObjectState(oPRBCalculation, Ease.Core.ObjectState.Saved);
        }
        protected override T CreateObject<T>(DataReader oReader)
        {
            PRBCalculation oPRBCalculation = new PRBCalculation();
            MapObject(oPRBCalculation, oReader);
            return oPRBCalculation as T;
        }
        protected PRBCalculation CreateObject(DataReader oReader)
        {
            PRBCalculation oPRBCalculation = new PRBCalculation();
            MapObject(oPRBCalculation, oReader);
            return oPRBCalculation;
        }

        #region Service implementation
        public PRBCalculation Get(int id)
        {
            PRBCalculation oPRBCalculation = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(PRBCalculationDA.Get(tc, id));
                if (oreader.Read())
                {
                    oPRBCalculation = this.CreateObject<PRBCalculation>(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 oPRBCalculation;
        }

        public PRBCalculation GetByEmployeeID(int id)
        {
            PRBCalculation oPRBCalculation = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(PRBCalculationDA.GetByEmployeeID(tc, id));
                if (oreader.Read())
                {
                    oPRBCalculation = this.CreateObject<PRBCalculation>(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 oPRBCalculation;
        }

        public PRBCalculation GetByEmployeeIDDecData(int id, DateTime prbYear)
        {
            PRBCalculation oPRBCalculation = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(PRBCalculationDA.GetByEmployeeIDDecData(tc, id, prbYear));
                if (oreader.Read())
                {
                    oPRBCalculation = this.CreateObject<PRBCalculation>(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 oPRBCalculation;
        }

        public List<PRBCalculation> GetByid(int id)
        {
            #region Cache Header

            List<PRBCalculation> procals = new List<PRBCalculation>();
            if (procals != null)
                return procals;

            #endregion

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

                DataReader dr = new DataReader(PRBCalculationDA.Get(tc, id));
                procals = this.CreateObjects<PRBCalculation>(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 procals;
        }

        public List<PRBCalculation> GetByBatchId(int batchId)
        {
            #region Cache Header

            List<PRBCalculation> procals = new List<PRBCalculation>();

            #endregion

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

                DataReader dr = new DataReader(PRBCalculationDA.GetByBatchId(tc, batchId));
                procals = this.CreateObjects<PRBCalculation>(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 procals;
        }

        public DataTable GetPrbAmountOfCurrentMonth(int batchId)
        {
            DataTable prbAmountCalculations = new DataTable();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                prbAmountCalculations = PRBCalculationDA.getPrbAmountOfCurrentMonth(tc, batchId);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

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

                #endregion
            }

            return prbAmountCalculations;
        }

        public List<PRBCalculation> GetByEmpIds(string sEmpIDs,DateTime prbYear,DateTime prbMonth)
        {
            List<PRBCalculation> prbCals = new List<PRBCalculation>();
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader dr = new DataReader(PRBCalculationDA.GetByEmpIDs(tc, sEmpIDs, prbYear, prbMonth));
                prbCals = this.CreateObjects<PRBCalculation>(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 prbCals;
        }

        public void InitiatePRBCalculationWorkFlow(int prbBatchID, int userID, int employeeid)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                InitiatePRBCalculationWorkFlow(tc, prbBatchID, employeeid, userID);
                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 InitiatePRBCalculationWorkFlow(TransactionContext tc, int prbbatchid, int initiateEmpID, int userID)
        {
            try
            {
                PRBCalculation item = new PRBCalculation();
                item.BatchID = prbbatchid;
                int prbsetupID = 10;
                Employee emp = new EmployeeService().Get(tc, initiateEmpID);
                string subject = " PRB Bonus Request has been raised" + " For " + item.EndDate.ToString("MMMM") + ". Your Approval is required";
                HRM.DA.WFManager<IworkflowInterface> om = new HRM.DA.WFManager<IworkflowInterface>(item);
                om.InitiateProcess(tc, initiateEmpID, prbsetupID, prbbatchid, "", subject); //which remarks?
                PRBCalculationDA.UpdatePrbStatus(tc, prbbatchid, EnumPRBStatus.Submitted);
            }
            catch (Exception e)
            {
                #region Handle Exception

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

                #endregion
            }

        }

        public void ApprovePRBBonus(WFMovementTran approver)
        {
            PRBCalculation item = this.Get(approver.ObjectID);
            TransactionContext tc = null;
            try
            {
              
                SearchEmployee s = new SearchEmployeeService().get(approver.FromEmployeeID);

                tc = TransactionContext.Begin(true);

                string subject = s.EmployeeNo + "-" + s.Name + " has approved your PRB Bonus Request on " + item.EndDate.ToString("dd/MM/yyyy");
                WFMovementTran newTran = new HRM.DA.WFManager<IworkflowInterface>().Approve(tc, approver.ID,
                    approver.FromEmployeeID, approver.Remarks, subject);
                if (newTran.Status == EnumwfStatus.End)
                {
                    PRBCalculationDA.ApproveOrRejectPrbStatus(tc, approver.ObjectID,
                        EnumPRBStatus.Approved, approver.UserID);
                }
                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 RejectPRBBonus(WFMovementTran approver)
        {
            PRBCalculation item = this.Get(approver.ObjectID);
            TransactionContext tc = null;
            try
            {

                SearchEmployee s = new SearchEmployeeService().get(approver.FromEmployeeID);

                tc = TransactionContext.Begin(true);

                string subject = s.EmployeeNo + "-" + s.Name + " has approved your PRB Bonus Request on " + item.EndDate.ToString("dd/MM/yyyy");
                WFMovementTran newTran = new HRM.DA.WFManager<IworkflowInterface>().Approve(tc, approver.ID,
                    approver.FromEmployeeID, approver.Remarks, subject);

                PRBCalculationDA.ApproveOrRejectPrbStatus(tc, approver.ObjectID,
                        EnumPRBStatus.Rejected, approver.UserID);

                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<ClaimBasic> Get(EnumStatus status, int payrollTypeID)
        //{
        //    List<ClaimBasic> claimBasics = null;

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

        //        DataReader dr = new DataReader(ClaimBasicDA.Get(tc, status, payrollTypeID));
        //        claimBasics = this.CreateObjects<ClaimBasic>(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 claimBasics;
        //}

        //public List<ClaimBasic> GetNew(EnumStatus status, int payrollTypeID)
        //{
        //    List<ClaimBasic> claimBasics = new List<ClaimBasic>();

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

        //        DataReader dr = new DataReader(ClaimBasicDA.GetNew(tc, status, payrollTypeID));
        //        claimBasics = this.CreateObjects<ClaimBasic>(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 claimBasics;
        //}

        public void Save(List<PRBCalculation> PRBCalculations)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                int id = tc.GenerateID("PRBCalculation", "PRBCalculationID");
                foreach (PRBCalculation oPRBCalculation in PRBCalculations)
                {
                    if (oPRBCalculation.IsNew)
                    {
                        oPRBCalculation.CreatedDate = DateTime.Now;
                        base.SetObjectID(oPRBCalculation, id);
                        PRBCalculationDA.Insert(tc, oPRBCalculation);
                        id++;
                    }
                    else
                    {
                        PRBCalculationDA.Update(tc, oPRBCalculation);
                    }
                }

                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 Save(List<PRBCalculation> PRBCalculations,DateTime prbMonth,DateTime prbYear,int userId)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                int getYear = (prbYear.Year) % 100; //last two digit
                int getMonth = prbMonth.Month;
                var builder = new StringBuilder();
                int batchId= Convert.ToInt32(builder.Append(getMonth).Append(getYear).ToString());
                int id = tc.GenerateID("PRBCalculation", "PRBCalculationID");
              
                var emids = PRBCalculations.Select(o => o.EmployeeID).Distinct().ToList();
                string empids= string.Join(",", emids);
                PRBCalculationDA.DeleteExistingData(tc, empids, prbMonth, prbYear);
                foreach (PRBCalculation oPRBCalculation in PRBCalculations)
                {
                    oPRBCalculation.CreatedDate = DateTime.Now;
                    oPRBCalculation.BatchID = batchId;
                    base.SetObjectID(oPRBCalculation, id);
                    PRBCalculationDA.Insert(tc, oPRBCalculation);
                    //if (oPRBCalculation.PRBStatus == EnumPRBStatus.Submitted)
                    //{
                    //    this.InitiatePRBCalculationWorkFlow(tc, oPRBCalculation, oPRBCalculation.EmployeeID, userId);
                    //}
                    id++;
                }
                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(int empid,DateTime prbMonth)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                PRBCalculationDA.Delete(tc, empid, prbMonth);
                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(int id)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                PRBCalculationDA.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
    }
    #endregion

  
}