using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ease.Core;
using Ease.Core.Model;
using System.Data;




namespace HRM.BO
{
    #region OPIProcessDetail
    
    public class OPIProcessDetail : BasicBaseObject
    {
        private List<Employee> _employees;
        private List<OPIProcessDetail> _processDetails;
        private List<OpiParameter> _opiParameters;
        private List<OpiItem> _opiItems;
       // private DataSet _dsOPIRegister;

       // private List<ProcessItem> _processItems;
        
        //private List<SalaryProcessStatus> _processStatuses;
        public DateTime _processMonth;

        //public event ProcessStatus ProcessStatus;
        //public event ProgressStatus ProgressStatus;

        

        #region Constructor
        public OPIProcessDetail()
        {
            //_accountNo = string.Empty;
            //_bankID = null;
            //_branchID = null;
            //_categoryID = null;
            //_departmentID = null;
            //_designationID = null;
            //_employeeID = null;
            //_gender = EnumGender.None;
            //_gradeID = null;
            //_isConfirmed = false;
            //_isFinalize = false;
            //_locationID = null;
            //_oPIProcessID = null;
            //_payrollTypeID = null;
            //_pfMemberType = EnumPFMembershipType.Live;
            //_religionID = null;
            //_remarks = string.Empty;
            //_oPIProcessDetailItems = null;
            //_gradeSalaries = null;
            //_employee = null;
            //_arreargradeSalaries = null;
            //_arrearPaidgradeSalaries = null;
            this.opiProcessDetailItems = new List<OPIProcessDetailItem>();
        }
        #endregion

        #region Properties

        public string AccountNo { get; set; }

        public int? BankID { get; set; }

        public int? BranchID { get; set; }

        public int? CategoryID { get; set; }

        public int? DepartmentID { get; set; }

        public int? DesignationID { get; set; }

        public int EmployeeID { get; set; }

        public EnumGender Gender { get; set; }

        public int? GradeID { get; set; }

        public bool IsConfirmed { get; set; }

        public bool IsFinalize { get; set; }

        public int? LocationID { get; set; }

        public int OPIProcessID { get; set; }

        public int PayrollTypeID { get; set; }

        public EnumPFMembershipType PFMemberType { get; set; }

        public int ReligionID { get; set; }

        public string Remarks { get; set; }

        public List<OPIProcessDetailItem> opiProcessDetailItems { get; set; }

        public Employee Employee { get; set; }
        //#region Employee : Employee
        //private Employee _employee;
        //public Employee Employee
        //{
        //    get
        //    {
        //        if (_employeeID.Integer > 0 && _employee == null)
        //        {
        //            _employee = new Employee();
        //            _employee = Payroll.BO.Employee.Get(_employeeID);
        //        }
        //        return this._employee;
        //    }
        //    set
        //    {
        //        _employee = value;
        //    }
        //}
        //#endregion

        public List<EmployeeGradeSalary> GradeSalaries { get; set; }

        public List<EmployeeGradeSalary> ArrearGradeSalaries { get; set; }

        public List<EmployeeGradeSalary> ArrearPaidGradeSalaries { get; set; }

        //#region Service Factory IOPIProcessDetailService : IOPIProcessDetailService
        //internal static IOPIProcessDetailService Service
        //{
        //    get
        //    {
        //        return Services.Factory.CreateService<IOPIProcessDetailService>(typeof(IOPIProcessDetailService));
        //    }
        //}

        //#endregion

        //public List<SalaryProcessStatus> Errors
        //{
        //    get
        //    {
        //        return _processStatuses;
        //    }
        //}

        #endregion

        //#region Functions
        //public static OPIProcessDetail Get(ID nOPIProcessDetailID)
        //{
        //    OPIProcessDetail oOPIProcessDetail = null;
        //    #region Cache Header
        //    oOPIProcessDetail = (OPIProcessDetail)_cache["Get", nOPIProcessDetailID];
        //    if (oOPIProcessDetail != null)
        //        return oOPIProcessDetail;
        //    #endregion
        //    oOPIProcessDetail = OPIProcessDetail.Service.Get(nOPIProcessDetailID);
        //    #region Cache Footer
        //    _cache.Add(oOPIProcessDetail, "Get", nOPIProcessDetailID);
        //    #endregion
        //    return oOPIProcessDetail;
        //}

        //public static List<OPIProcessDetail> Get()
        //{
        //    #region Cache Header
        //    List<OPIProcessDetail> oOPIProcessDetails = _cache["Get"] as List<OPIProcessDetail>;
        //    if (oOPIProcessDetails != null)
        //        return oOPIProcessDetails;
        //    #endregion
        //    try
        //    {
        //        oOPIProcessDetails = Service.Get();
        //    }
        //    catch (ServiceException e)
        //    {
        //        throw new Exception(e.Message, e);
        //    }
        //    #region Cache Footer
        //    _cache.Add(oOPIProcessDetails, "Get");
        //    #endregion
        //    return oOPIProcessDetails;
        //}
        //public ID Save()
        //{
        //    this.SetAuditTrailProperties();
        //    return OPIProcessDetail.Service.Save(this);
        //}
        //public void Delete(ID id)
        //{
        //    OPIProcessDetail.Service.Delete(id);
        //}

        //#region ProgressBar
        //private void UpdateprocessStatus(string statusString)
        //{
        //    if (ProcessStatus != null) ProcessStatus(statusString);
        //}
        //private void UpdateProgressStatus(EnumProcessStatus status)
        //{
        //    if (ProgressStatus != null) ProgressStatus(status);
        //}
        //#endregion

        //public List<OPIProcessDetail> Process(List<Employee> employees, DateTime processMonth)
        //{
        //    //SalaryException oSException = new SalaryException();
        //    _employees = employees;
        //    _processMonth = processMonth;

        //    UpdateprocessStatus("Collecting Employee basic information....");
        //    //this.Initialize();
        //    this.AddEmployeeToProcessDetail();

        //    //if (_processStatuses.Count > 0) return;
        //    UpdateprocessStatus("Calculating Employee basic Salary....");
        //    this.BasicSalary();
        //    UpdateprocessStatus("Calculating Employees benifits and deduction....");
        //    this.OPIItems();

        //    //this.LeavePrepare(oSException.GetEmpLeaveStatus());
        //    return _processDetails;
        //}
        //private void AddEmployeeToProcessDetail()
        //{
        //    _processDetails = new List<OPIProcessDetail>();

        //    UpdateProgressStatus(EnumProcessStatus.Start);
        //    foreach (Employee employee in _employees)
        //    {
        //        UpdateProgressStatus(EnumProcessStatus.PerformStep);
        //        PayrollPayrollGlobalFunctions.UpdateStatus(" Collecting information for the employee " + employee.Name + " ( " + employee.EmployeeNo + ")");

        //        OPIProcessDetail procDetail = new OPIProcessDetail();
        //        procDetail.CategoryID = employee.CategoryID;
        //        procDetail.EmployeeID = employee.ID;
        //        procDetail.Gender = employee.Gender;
        //        procDetail.IsConfirmed = employee.IsConfirmed;
        //        procDetail.PayrollTypeID = employee.PayrollTypeID;
        //        procDetail.PFMemberType = employee.PFMemberType;

        //        procDetail.ReligionID = employee.ReligionID;
        //        procDetail.GradeID = employee.GradeID;
        //        procDetail.DepartmentID = employee.DepartmentID;
        //        procDetail.DesignationID = employee.DesignationID;
        //        procDetail.LocationID = employee.LocationID;

        //        if (employee.PaymentMode == EnumPaymentMode.BankTransfer)
        //        {
        //            procDetail.BranchID = employee.BranchID;

        //            Branch branch = new Branch();
        //            branch = Branch.Get(employee.BranchID);
        //            procDetail.BankID = branch.BankID;

        //            procDetail.AccountNo = employee.AccountNo;
        //        }
        //        else
        //        {
        //            procDetail.BranchID = ID.FromInteger(0);
        //            procDetail.BankID = ID.FromInteger(0);
        //        }
                
        //        procDetail.Employee = employee;

        //        _processDetails.Add(procDetail);
        //    }
        //    UpdateProgressStatus(EnumProcessStatus.End);
        //}
        //private void AddProcessStatus(Employee employee, string remarks)
        //{
        //    SalaryProcessStatus status = new SalaryProcessStatus();
        //    status.EmployeeNo = employee.EmployeeNo;
        //    status.Name = employee.Name;
        //    status.Remarks = remarks;
        //    _processStatuses.Add(status);
        //}


        //private void BasicSalary()
        //{
        //    //GetCurrentMonthSalaryItems function return current month's employee grade, salary and effect date.
        //    //effect date must sorted, otherwise error will be generated from next function.
        //    #region Calculate Normal Salary
        //    List<EmployeeGradeSalary> gradeSalaryItems = EmployeeGradeSalary.Service.GetCurrMonthSalaryItems(SystemInformation.CurrentSysInfo.NextPayProcessDate);
        //    foreach (OPIProcessDetail  opiProcess in _processDetails )
        //    {
        //        opiProcess.GradeSalaries = EmployeeGradeSalary.Get(gradeSalaryItems, opiProcess.EmployeeID);
        //        if (opiProcess.GradeSalaries.Count == 0) continue;
        //        EmployeeGradeSalary.PrepareDataForCurrentSalary(opiProcess.Employee, opiProcess.GradeSalaries);
        //    }
        //    #endregion Calculate Normal Salary
            
        //    #region calculate arrear amount
        //    List<EmployeeGradeSalary> arrearItems = EmployeeGradeSalary.Service.GetArrearItems(SystemInformation.CurrentSysInfo.PayrollTypeID.Integer);
        //    foreach (OPIProcessDetail opiProcess in _processDetails)
        //    {
        //        opiProcess.ArrearGradeSalaries = EmployeeGradeSalary.Get(arrearItems, opiProcess.EmployeeID);
        //        if (opiProcess.ArrearGradeSalaries.Count > 0)
        //        {
        //            DateTime arrearPaidFrom = opiProcess.ArrearGradeSalaries[0].EffectDate;
        //            opiProcess.ArrearPaidGradeSalaries = EmployeeGradeSalary.Service.GetArrearPaidItems(opiProcess.EmployeeID, arrearPaidFrom,SystemInformation.CurrentSysInfo.PayrollTypeID.Integer);
        //        }
        //    }
        //    #endregion calculate arrear amount
        //}
        //private void OPIItems()
        //{
        //    _opiParameters = OpiParameter.Get(EnumStatus.Active);
        //    if (_opiParameters == null || _opiParameters.Count == 0) return;

        //    List<OpiParameterIndividual> opiIndividuals = OpiParameterIndividual.Service.Get(
        //                            PayrollPayrollGlobalFunctions.PayrollFirstDateOfMonth(_processMonth),
        //                            PayrollPayrollGlobalFunctions.PayrollLastDateOfMonth(_processMonth));
        //    OpiParameter paramter = new OpiParameter();
        //    List<OpiParameter> paramters;
        //    foreach (OPIProcessDetail detail in _processDetails)
        //    {
        //        // Regular Grade defined parameters
        //        paramters = paramter.ApplicableParameters(detail.Employee, 
        //                                detail, _opiParameters, detail.GradeSalaries);
        //        this.GradeDefinedOpiItem(detail, detail.GradeSalaries, paramters);
                
        //        // Arrear Grade defined parameters
        //        paramters = paramter.ApplicableParameters(detail.Employee,
        //                detail, _opiParameters, detail.ArrearGradeSalaries);
        //        this.GradeDefinedOpiItem(detail, detail.GradeSalaries, paramters);

        //        // Arrear already paid parameters
        //        paramters = paramter.ApplicableParameters(detail.Employee,
        //                detail, _opiParameters, detail.ArrearPaidGradeSalaries);
        //        this.GradeDefinedOpiItem(detail, detail.GradeSalaries, paramters);
        //        //this.IndividualOpiItem(detail, opiIndividuals);
        //    }
        //}

        //private void Add(OPIProcessDetail processDetail, OPIProcessDetailItem item)
        //{
        //    OPIProcessDetailItem existItem = processDetail.OPIProcessDetailItems.Find(delegate(OPIProcessDetailItem fItem) { return fItem.OPIItemID == item.OPIItemID; });
        //    if (existItem == null)
        //    {
        //        processDetail.OPIProcessDetailItems.Add(item);
        //    }
        //    else
        //    {
        //        existItem.NetAmount = existItem.NetAmount + item.NetAmount;
        //        existItem.ChangeNetAmount = existItem.ChangeNetAmount + item.ChangeNetAmount;
        //        existItem.Description = item.Description;
        //    }
        //}
        //private void GradeDefinedOpiItem(OPIProcessDetail detail, List<EmployeeGradeSalary> gradeSalaries,
        //    List<OpiParameter> paramters)
        //{
        //    double amount = 0, totalAmount = 0, paidAmount = 0, remainingAmount;
        //    int totalMonth = 12, paidMonth = 0, remainingMonth = 0;

        //    //int randomEmployee = (new Random()).Next(1, _employees.Count);
        //    int empNumber = 1;
            
        //    foreach (EmployeeGradeSalary empGradeSalary in gradeSalaries)
        //    {
        //        foreach (OpiParameter parameter in paramters)
        //        {
        //            if (parameter.EntitleType == EnumEntitleType.Grade)
        //            {
        //                //amount = parameter.GetGradeDefinedAmount(detail.Employee, empGradeSalary.BasicSalary, empGradeSalary.GrossSalary);
        //                if (parameter.IsFlatAmount == true) amount = amount * empGradeSalary.FractionofFromTo;
        //            }
        //            else  continue;

        //            OPIProcessDetailItem opdItem = new OPIProcessDetailItem();
        //            switch (parameter.OpiPeriodicity)
        //            {
        //                case EnumOpiPeriodicity.Monthly:
        //                    opdItem.NetAmount = amount;
        //                    opdItem.ChangeNetAmount = amount;
        //                    //opdItem.TaxAmount = 
        //                    break;
        //                case EnumOpiPeriodicity.OnceOff:
        //                    opdItem.NetAmount = amount;
        //                    opdItem.ChangeNetAmount = amount;
        //                    //opdItem.TaxAmount = 
        //                    break;
        //                case EnumOpiPeriodicity.Annual:
        //                    paidMonth = Convert.ToInt32(Payroll.BO.SystemInformation.CurrentSysInfo.NextPayProcessDate.Date.Month);
        //                    remainingMonth = totalMonth - (paidMonth);

        //                    totalAmount = amount * totalMonth;
        //                    paidAmount = paidMonth * amount;
        //                    remainingAmount = totalAmount - paidAmount;

        //                    opdItem.NetAmount = remainingAmount / remainingMonth;
        //                    opdItem.ChangeNetAmount = remainingAmount / remainingMonth;
        //                    //opdItem.TaxAmount = 
        //                    break;
        //                //case EnumOpiPeriodicity.AveragePayment:

        //                //    break;
        //                //case EnumOpiPeriodicity.OnAmount:
        //                //    indvAmnt = amount / _processDetails.Count;
        //                //    fractionAmount = (indvAmnt - Math.Round(indvAmnt, 0)) * _processDetails.Count;

        //                //    if (empNumber == gradeSalaries.Count)
        //                //    {
        //                //        opdItem.NetAmount = Math.Round(indvAmnt, 0) + fractionAmount;
        //                //        opdItem.ChangeNetAmount = Math.Round(indvAmnt, 0) + fractionAmount;
        //                //    }
        //                //    else
        //                //    {
        //                //        opdItem.NetAmount = Math.Round(indvAmnt, 0);
        //                //        opdItem.ChangeNetAmount = Math.Round(indvAmnt, 0);
        //                //    }
        //                //    //opdItem.TaxAmount = 
        //                //    break;
        //                default:
        //                    break;
        //            }

        //            opdItem.Description = parameter.OpiItem.Name;
        //            opdItem.OPIItemID = parameter.OpiItemID;
        //            opdItem.OPIProcessDetailID = this.ID;
        //            opdItem.OPIType = parameter.OpiItem.OpiType;
                    
        //            _opiItems = OpiItem.Get();
        //            if (_opiItems != null && _opiItems.Count > 0)
        //                opdItem.Sequence = _opiItems.GetItem(parameter.OpiItem.ID).Sequence;

        //            this.Add(detail, opdItem); // add the item in the collection
        //        }
        //        empNumber++;
        //    }
        //}
        //private void IndividualOpiItem(OPIProcessDetail detail, List<OpiParameterIndividual> opiIndividuals)
        //{
        //    //double amount = 0;
        //    //EnumSalaryGroup groupCode = EnumSalaryGroup.Gross;
        //    //#region Individual Allowance
        //    //List<OpiParameterIndividual> items = opiIndividuals.FindAll(delegate(OpiParameterIndividual item)
        //    //{
        //    //    return item.EmployeeId.Integer == detail.Employee.ID.Integer && item.IndividualType == EnumOPIIndivdualType.AppliedToIndividual;
        //    //});
        //    //foreach (OpiParameterIndividual item in items)
        //    //{
        //    //    amount = 0;
        //    //    OpiParameter parameter = _opiParameters.GetItem(item.OpiParameterID);

        //    //    amount = parameter.GetIndividualAmount(detail.Employee, _processMonth, item,
        //    //            detail.Employee.GrossSalary, detail.GetGrossAmount(EnumSalaryItemCode.Basic_Salary, (int)EnumSalaryItemCode.Basic_Salary));

        //    //    EnumSalaryItemCode itemCode = EnumSalaryItemCode.Allowance;
        //    //    groupCode = EnumSalaryGroup.Gross;
        //    //    if (parameter.AllowOrDeductType == EnumAllowOrDeduct.Deduction)
        //    //    {
        //    //        itemCode = EnumSalaryItemCode.Deduction;
        //    //        groupCode = EnumSalaryGroup.Deductions;
        //    //    }
        //    //    if (item.Arreartype == EnumArrearType.ToCalculate) groupCode = EnumSalaryGroup.Arrear;

        //    //    SalaryMonthlyDetail detail = salary.GetDetail(groupCode, itemCode, parameter.AllowDeductID.Integer);
        //    //    if (detail == null)
        //    //        detail = this.AddDetail(salary, groupCode, itemCode, parameter.AllowDeductID.Integer, parameter.ID.Integer, parameter.AllowanceDeduction.Name, amount);
        //    //    else
        //    //    {
        //    //        detail.CalculatedAmount = detail.CalculatedAmount + amount;
        //    //        detail.CalculatedAmount = PayrollPayrollGlobalFunctions.Round(detail.CalculatedAmount);
        //    //        detail.ChangedAmount = detail.CalculatedAmount;
        //    //    }
        //    //    detail.Position = item.AllowDeduct.Sequence + 1;
        //    //}

        //    //#endregion Individual Allowance
        //}
        //#endregion

        //public static List<OPIProcessDetail> GetDetail(DateTime _SalaryMonth)
        //{
        //    #region Cache Header
        //    List<OPIProcessDetail> oOPIProcessDetails = _cache["Get"] as List<OPIProcessDetail>;
        //    if (oOPIProcessDetails != null)
        //        return oOPIProcessDetails;
        //    #endregion
        //    try
        //    {
        //        oOPIProcessDetails = Service.Get(_SalaryMonth);
        //    }
        //    catch (ServiceException e)
        //    {
        //        throw new Exception(e.Message, e);
        //    }
        //    #region Cache Footer
        //    _cache.Add(oOPIProcessDetails, "Get");
        //    #endregion
        //    return oOPIProcessDetails;
        //}
    }
    #endregion

    //#region IOPIProcessDetail Service
    //public interface IOPIProcessDetailService
    //{
    //    OPIProcessDetail Get(ID id);

    //    List<OPIProcessDetail> Get();
    //    ID Save(OPIProcessDetail item);
    //    void Save(OPIProcess oProcess, List<OPIProcessDetail> oPDetails);
    //    void Delete(ID id);


    //    List<OPIProcessDetail> Get(DateTime _SalaryMonth);
    //}
    //#endregion
}