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

namespace HRM.BO
{

    public class DefaultConfigurationValue
    {

        public DefaultConfigurationValue()
        {

        }
        public DefaultConfigurationValue(int _roundDigit, string _dayFractionType, bool _isMidPointRound)
        {
            roundOfDigit = _roundDigit;
            DayFactionType = _dayFractionType;
            IsMidPointRound = _isMidPointRound;

        }
        public int roundOfDigit { get; }

        public string DayFactionType { get; }
        public bool IsMidPointRound { get; }

    }


    public class GlobalFunctions
    {
        private static DefaultConfigurationValue _defaultConfigVal;
        public static bool bDataFound = false;
        public static DefaultConfigurationValue defaultConfigVal
        {
            get
            {
                if (_defaultConfigVal == null)
                {
                    _defaultConfigVal = GlobalFunctions.Service.RefreshServerValue();
                }
                return _defaultConfigVal;
            }

            set
            {
                _defaultConfigVal = value;
            }
        }

        #region Service Factory IGlobalFunctionService : IGlobalFunctionService

        internal static IGlobalFunctionService Service
        {
            get { return Services.Factory.CreateService<IGlobalFunctionService>(typeof(IGlobalFunctionService)); }
        }

        public static int MONTH_START_DATE { get; set; }

        #endregion


        public static string GetApiDefaultData(string str)
        {
            str = (str == "" || str == "null" || str == "undefined") ? string.Empty : str;
            return str;
        }

        public static int? GetApiDefaultIntData(string str)
        {
            int? intData = null; ;
            if (str != null && str != "" && str.ToLower() != "null" && str.ToLower() != "undefined")
            {
                intData = Convert.ToInt32(str);
            }
            return intData;
        }

        
        public static DateTime GetApiDefaultDateData(string str)
        {
            DateTime dateData = DateTime.MinValue;
            if (str != null && str != "" && str.ToLower() != "null" && str.ToLower() != "undefined")
            {
                dateData = Convert.ToDateTime(str);
            }
            return dateData;
        }

        public static string AgeCalculate(DateTime Bday, DateTime Cday)
        {
            int Years = 0;
            int Months = 0;
            int Days = 0;

            if ((Cday.Year - Bday.Year) > 0 ||
                (((Cday.Year - Bday.Year) == 0) && ((Bday.Month < Cday.Month) ||
                ((Bday.Month == Cday.Month) && (Bday.Day <= Cday.Day)))))
            {
                int DaysInBdayMonth = DateTime.DaysInMonth(Bday.Year, Bday.Month);
                int DaysRemain = Cday.Day + (DaysInBdayMonth - Bday.Day);

                if (Cday.Month > Bday.Month)
                {
                    Years = Cday.Year - Bday.Year;
                    Months = Cday.Month - (Bday.Month + 1) + Math.Abs(DaysRemain / DaysInBdayMonth);
                    Days = (DaysRemain % DaysInBdayMonth + DaysInBdayMonth) % DaysInBdayMonth;
                }
                else if (Cday.Month == Bday.Month)
                {
                    if (Cday.Day >= Bday.Day)
                    {
                        Years = Cday.Year - Bday.Year;
                        Months = 0;
                        Days = Cday.Day - Bday.Day;
                    }
                    else
                    {
                        Years = (Cday.Year - 1) - Bday.Year;
                        Months = 11;
                        Days = DateTime.DaysInMonth(Bday.Year, Bday.Month) - (Bday.Day - Cday.Day);
                    }
                }
                else
                {
                    Years = (Cday.Year - 1) - Bday.Year;
                    Months = Cday.Month + (11 - Bday.Month) + Math.Abs(DaysRemain / DaysInBdayMonth);
                    Days = (DaysRemain % DaysInBdayMonth + DaysInBdayMonth) % DaysInBdayMonth;
                }
            }
            else
            {
                throw new ArgumentException("Birthday date must be earlier than current date");
            }

            return Years + " Years, " + Months + " Months, " + Days + " Days";
        }

        //public static DateTime GetOperationDate()
        //{
        //    try
        //    {
        //        return Service.GetOperationDate();
        //    }
        //    catch (ServiceException e)
        //    {
        //        throw new Exception(e.Message, e);
        //    }
        //}
        public static string GetShortAttnType(EnumAttendanceType atype, EnumWorkPlanDayType daytype, double latehour)
        {
            string type = string.Empty;
            switch (atype)
            {
                case EnumAttendanceType.Absent:
                    type = "AB";
                    break;

                case EnumAttendanceType.Delay:
                    type = "LP";
                    break;

                case EnumAttendanceType.Holiday:
                    type = "H";
                    break;

                case EnumAttendanceType.Late:
                    type = "LP";
                    break;

                case EnumAttendanceType.Leave:
                    type = "Lv";
                    break;

                case EnumAttendanceType.Present:
                    type = "PR";

                    if (daytype == EnumWorkPlanDayType.WorkingDay &&
                              latehour > 0)
                    {
                        type = "L-PR";
                    }
                    else if (daytype == EnumWorkPlanDayType.WeeklyHoliday 
                         && latehour > 0)
                    {
                        type = "WD-L-PR";

                    }
                    else if (daytype == EnumWorkPlanDayType.WeeklyHoliday &&
                            latehour <= 0)
                    {
                        type = "WD-PR";
                    }
                    else if (daytype == EnumWorkPlanDayType.NationalHoliday &&
                         latehour > 0)
                    {
                        type = "H-L-PR";

                    }
                    else if (daytype == EnumWorkPlanDayType.NationalHoliday &&
                           latehour <= 0)
                    {
                        type = "H-PR";

                    }

                    break;


                case EnumAttendanceType.OutSideDuty:
                    type = "OD";
                    break;

                case EnumAttendanceType.Early:
                    type = "E";
                    break;

                case EnumAttendanceType.WeeklyHoliday:
                    type = "WD";
                    break;
            }
            return type;
        }

        public static double GetHourtoMinutes(double hours)
        {
            return Math.Floor(hours) * ((hours - Math.Floor(hours))/100);
        }

        public static double GetOTDailyRate(double nBasic, DateTime dMonthDate)
        {
            double amount = 0;
            amount = nBasic / Convert.ToDouble(DateTime.DaysInMonth(dMonthDate.Year, dMonthDate.Month));
            return amount;
        }

        public static double GetOTHourlyRate(double nBasic, DateTime dMonthDate)
        {
            double amount = 0;
            int hours = 0;//ConfigurationManager.GetIntValue("overtime", "hoursonmonth", EnumConfigurationType.Logic);
            if (hours <= 0) hours = 208;
            double doubleHOur = Convert.ToDouble(hours);
            amount = nBasic / doubleHOur;
            return amount;

        }
        public static double ConvertToDailyRate(double nBasic, DateTime dMonthDate)
        {
            enumfractionCalculatinType ntype = getFractionateCalType();
            double amount = 0;

            switch (ntype)
            {
                case enumfractionCalculatinType.Monthly:
                    amount = nBasic / Convert.ToDouble(DateTime.DaysInMonth(dMonthDate.Year, dMonthDate.Month));
                    break;
                case enumfractionCalculatinType.Yearly:
                    amount = (nBasic * 12) / 365;
                    break;
                case enumfractionCalculatinType.ThirtyDaysMonth:
                case enumfractionCalculatinType.ThirtyDaysMonthActual:
                    amount = nBasic / 30;
                    break;
                default:
                    break;
            }
            return amount;
        }

        public static int GetDaysInMonth(DateTime dMonthDate)
        {
            enumfractionCalculatinType ntype = getFractionateCalType();
            int amount = 0;

            switch (ntype)
            {
                case enumfractionCalculatinType.Monthly:
                    amount = DateTime.DaysInMonth(dMonthDate.Year, dMonthDate.Month);
                    break;
                case enumfractionCalculatinType.ThirtyDaysMonthActual:
                case enumfractionCalculatinType.ThirtyDaysMonth:
                    amount = 30;
                    break;
                default:
                    amount = 30;
                    break;
            }
            return amount;
        }

        public static string ConvertDoubleHourToHourMinute(double totalHour)
        {
            string[] strParts = totalHour.ToString("0.000000").Split('.');
            strParts[1] = "." + strParts[1];

            string hourPart = Convert.ToInt32(strParts[0]).ToString("00");
            string minutepart = Math.Round(Convert.ToDecimal(strParts[1]) * 60, 0, MidpointRounding.AwayFromZero).ToString("00");

            return string.Format("{0}:{1}", hourPart, minutepart);
        }
        public static string GetShortAttnType(EnumAttendanceType attnType)
        {
            string type = string.Empty;
            switch (attnType)
            {
                case EnumAttendanceType.Absent:
                    type = "A";
                    break;

                case EnumAttendanceType.Delay:
                    type = "L";
                    break;

                case EnumAttendanceType.Holiday:
                    type = "H";
                    break;

                case EnumAttendanceType.Late:
                    type = "L";
                    break;

                case EnumAttendanceType.Leave:
                    type = "Lv";
                    break;

                case EnumAttendanceType.Present:
                    type = "P";
                    break;


                case EnumAttendanceType.OutSideDuty:
                    type = "OD";
                    break;

                case EnumAttendanceType.Early:
                    type = "E";
                    break;

                case EnumAttendanceType.WeeklyHoliday:
                    type = "W";
                    break;
            }
            return type;
        }

        public static string BloodGroupToBangla(EnumBloodGroup eBloodGrp)
        {
            string str = string.Empty;
            switch (eBloodGrp)
            {
                case EnumBloodGroup.None:
                    break;
                case EnumBloodGroup.APos:
                    str = "G cwRwUf";
                    break;
                case EnumBloodGroup.ANeg:
                    str = "G ‡b‡MwUf";
                    break;
                case EnumBloodGroup.BPos:
                    str = "we cwRwUf";
                    break;
                case EnumBloodGroup.BNeg:
                    str = "we ‡b‡MwUf";
                    break;
                case EnumBloodGroup.OPos:
                    str = "I cwRwUf";
                    break;
                case EnumBloodGroup.ONeg:
                    str = "I ‡b‡MwUf";
                    break;
                case EnumBloodGroup.ABPos:
                    str = "Gwe cwRwUf";
                    break;
                case EnumBloodGroup.ABNeg:
                    str = "Gwe ‡b‡MwUf";
                    break;
                default:
                    break;
            }

            return str;
        }

        public static string GetFullAttnType(EnumAttendanceType attnType)
        {
            Regex r = new Regex(@"(?<=[A-Z])(?=[A-Z][a-z])|(?<=[^A-Z])(?=[A-Z])|(?<=[A-Za-z])(?=[^A-Za-z])");
            return r.Replace(attnType.ToString(), " ");
        }

        //public static DateTime AttendanceMonthStart(DateTime date)
        //{
        //    if (date.Day > 20)
        //        return new DateTime(date.Year, date.Month, 21);
        //    else if (date.Month == 1)
        //        return new DateTime(date.Year - 1, 12, 21);
        //    else return new DateTime(date.Year, date.AddMonths(-1).Month, 21);
        //}
        //public static DateTime AttendanceMonthEnd(DateTime date)
        //{
        //    if (date.Day < 20)
        //        return new DateTime(date.Year, date.Month, 20);
        //    else
        //        if (date.Month == 12)
        //        return new DateTime(date.Year + 1, 1, 20);
        //    else return new DateTime(date.Year, date.AddMonths(1).Month, 20);
        //}

        //public static DateTime GetServerDate()
        //{
        //    object serverDate = null;
        //    try
        //    {
        //        serverDate = Service.GetServerDate();
        //    }
        //    catch (ServiceException e)
        //    {
        //        throw new ServiceException(e.Message, e);
        //    }
        //    return Convert.ToDateTime(serverDate);
        //}
        //public static DataTable AvailableUserObject()
        //{
        //    DataTable dataTable = new DataTable();
        //    try
        //    {
        //        dataTable = Service.AvailableUserObject();
        //    }
        //    catch (ServiceException e)
        //    {
        //        throw new ServiceException(e.Message, e);
        //    }
        //    return dataTable;
        //}

        public static string TagSQL(string sPrevious, string sNew)
        {
            string sSearch = string.Empty;
            if (sPrevious == string.Empty)
            {
                return sSearch = " Where " + sNew;
            }
            else
            {
                return sSearch = sPrevious + " And " + sNew;
            }

        }

        public static void ExportToExcel(StreamWriter wr, DataTable dt)
        {
            try
            {
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    wr.Write(dt.Columns[i].ToString().ToUpper() + "\t");
                }

                wr.WriteLine();

                //write rows to excel file
                for (int i = 0; i < (dt.Rows.Count); i++)
                {
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        if (dt.Rows[i][j] != null)
                        {
                            wr.Write(Convert.ToString(dt.Rows[i][j]) + "\t");
                        }
                        else
                        {
                            wr.Write("\t");
                        }
                    }
                    //go to next line
                    wr.WriteLine();
                }
                //close file
                wr.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static int GetDayofWeek(DateTime FromDate, DateTime ToDate, int day)
        {
            int i;
            DateTime dateTemp;
            i = 0;

            dateTemp = FromDate;


            while (dateTemp <= ToDate)
            {
                if (((int)dateTemp.DayOfWeek == day)) i = i + 1;
                dateTemp = dateTemp.AddDays(1);
            }

            return i;
        }
        public static DateTime GetAttandaceSalaryMonth(DateTime dDate)
        {
            return GetAttandaceSalaryMonth(dDate, -1);

        }
        public static DateTime GetAttandaceSalaryMonth(DateTime dDate, int MonthStartDate)
        {
            if (MonthStartDate == 1) // Fisrt date of Current Month
            {
                return Global.DateFunctions.LastDateOfMonth(dDate);
            }
            else if (MonthStartDate == -1) // Fisrt date of Current Month
            {
                dDate = dDate.AddMonths(-1);
                return Global.DateFunctions.LastDateOfMonth(dDate.AddMonths(1));
            }
            else
            {
                if (dDate.Day >= MonthStartDate)
                    return Global.DateFunctions.LastDateOfMonth(dDate.AddMonths(1));
                else return Global.DateFunctions.LastDateOfMonth(dDate);
            }
        }


        public static DateTime AttendanceMonthStart(DateTime date, int MonthStartDate)
        {
            if (MonthStartDate == 1) // Fisrt date of Current Month
            {
                return new DateTime(date.Year, date.Month, 1);
            }
            else if (MonthStartDate == -1) // Fisrt date of Current Month
            {
                date = date.AddMonths(-1);
                return new DateTime(date.Year, date.Month, 1);
            }
            else
            {
                if (date.Day > MonthStartDate)
                    return new DateTime(date.Year, date.Month, MonthStartDate);
                else if (date.Month == 1)
                    return new DateTime(date.Year - 1, 12, MonthStartDate);
                else return new DateTime(date.Year, date.AddMonths(-1).Month, MonthStartDate);
            }
        }
        public static DateTime AttendanceMonthEnd(DateTime date, int MonthStartDate)
        {
            if (MonthStartDate == 1) // Fisrt date of Current Month
            {
                return Global.DateFunctions.LastDateOfMonth(date);
            }
            else if (MonthStartDate == -1) // Fisrt date of Current Month
            {
                date = date.AddMonths(-1);
                return Global.DateFunctions.LastDateOfMonth(date);
            }
            else
            {
                if (date.Day < MonthStartDate)
                    return new DateTime(date.Year, date.Month, MonthStartDate);
                else
                if (date.Month == 12)
                    return new DateTime(date.Year + 1, 1, MonthStartDate);
                else return new DateTime(date.Year, date.AddMonths(1).Month, MonthStartDate);
            }
        }

        //public static DateTime GetCurrentDate()
        //{
        //    object currentDate = null;
        //    try
        //    {
        //        currentDate = Service.GetCurrentDate();
        //    }
        //    catch (ServiceException e)
        //    {
        //        throw new ServiceException(e.Message, e);
        //    }
        //    return Convert.ToDateTime(currentDate);
        //}

        //private static ErrorProvider _err = new ErrorProvider();

        //public static void CatchError(Control ctrl, string msg)
        //{
        //    _err.Clear();
        //    _err.BlinkRate = 250;
        //    _err.BlinkStyle = ErrorBlinkStyle.BlinkIfDifferentError;
        //    _err.SetError(ctrl, msg);
        //}


        public static double Round(double value)
        {
            double roundedValue = 0.00;
            try
            {


                roundedValue = Math.Round(value, GetRoundOfDigit(), MidpointRounding.AwayFromZero);
                //                roundedValue = Math.Round(value,2, MidpointRounding.AwayFromZero);

            }
            catch (Exception ex)
            {
                throw new ServiceException(ex.InnerException.Message);
            }

            return roundedValue;
        }

        public static double Round(double value, int roundofdegit)
        {
            double roundedValue = 0.00;
            try
            {
                roundedValue = Math.Round(value, GetRoundOfDigit(roundofdegit), MidpointRounding.AwayFromZero);

            }
            catch (Exception ex)
            {
                throw new ServiceException(ex.InnerException.Message);
            }

            return roundedValue;
        }

        public static double ConvertToHourlyRate(double nBasic)
        {
            double amount = 0;
            int hours = 0;//ConfigurationManager.GetIntValue("overtime", "hoursonmonth", EnumConfigurationType.Logic);
            if (hours <= 0) hours = 208;
            double doubleHOur = Convert.ToDouble(hours);
            amount = nBasic / doubleHOur;
            return amount;
        }

        public static enumfractionCalculatinType getFractionateCalType()
        {
            enumfractionCalculatinType type = enumfractionCalculatinType.Monthly;
            string caltype = GlobalFunctions.defaultConfigVal.DayFactionType; //ConfigurationManager.GetStringValue("root", "monthfraction", EnumConfigurationType.Logic);
            if (caltype.ToUpper() == "THIRTYDAYS")
                type = enumfractionCalculatinType.ThirtyDaysMonth;
            else if (caltype.ToUpper() == "THIRTYDAYSACTUAL")
                type = enumfractionCalculatinType.ThirtyDaysMonthActual;
            else if (caltype.ToUpper() == "YEARLY")
                        type = enumfractionCalculatinType.Yearly;
            else
                type = enumfractionCalculatinType.Monthly;
            return type;
        }
        //public static int GetdaysInMonth(DateTime dMonth)
        //{
        //    int daysinMonth = 30;
        //    enumfractionCalculatinType type = enumfractionCalculatinType.Monthly;
        //    string caltype = GlobalFunctions.defaultConfigVal.DayFactionType; //ConfigurationManager.GetStringValue("root", "monthfraction", EnumConfigurationType.Logic);
        //    if (caltype.ToUpper() == "THIRTYDAYS")
        //        daysinMonth = 30;
        //    else
        //        daysinMonth = GlobalFunctions.FirstDateOfMonth(dMonth) - GlobalFunctions.LastDateOfMonth(dMonth) 
        //    return type;
        //}

        public static double GetFraction(DateTime StartDate, DateTime EndDate)
        {
            double WorkDays;
            double MonDays;
            double TotFract;
            double nFraction = 1;
            TotFract = 0;
            //  bool isYearly = ConfigurationManager.GetBoolValue("root", "fractionalcalculationyearly", EnumConfigurationType.Logic);
            //bool isYearly = ConfigurationManager.GetBoolValue("root", "fractionalcalculation", EnumConfigurationType.Logic);
            enumfractionCalculatinType ntype = getFractionateCalType();
            WorkDays = Global.DateFunctions.DateDiff("d", StartDate,
                     GlobalFunctions.LastDateOfMonth(StartDate)) + 1;
            switch (ntype)
            {
                case enumfractionCalculatinType.Monthly:
                    while (StartDate <= EndDate)
                    {
                        WorkDays = Global.DateFunctions.DateDiff("d", StartDate,
                            GlobalFunctions.LastDateOfMonth(StartDate)) + 1;

                        MonDays = Global.DateFunctions.DateDiff("d",
                            GlobalFunctions.FirstDateOfMonth(StartDate),
                            GlobalFunctions.LastDateOfMonth(StartDate)) + 1;
                        if (StartDate.Month == EndDate.Month && EndDate != GlobalFunctions.LastDateOfMonth(EndDate))
                        {
                            WorkDays = Global.DateFunctions.DateDiff("d",
                                    GlobalFunctions.FirstDateOfMonth(EndDate), EndDate) + 1;
                        }
                        TotFract = TotFract + WorkDays / MonDays;
                        StartDate = GlobalFunctions.LastDateOfMonth(StartDate).AddDays(1);
                    }
                    nFraction = TotFract;
                    break;
                case enumfractionCalculatinType.Yearly:
                    //0.032876712328767123287671232876712
                    //0.0328767123
                    //if (StartDate == GlobalFunctions.FirstDateOfMonth(StartDate) && EndDate == GlobalFunctions.LastDateOfMonth(EndDate))
                    //{
                    //    WorkDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("m", StartDate, EndDate) + 1;
                    //    nFraction = WorkDays;
                    //}
                    //else
                    //{
                    //    WorkDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d", StartDate, EndDate) + 1;
                    //    double yearlyFraction = 0.0328767123; // which mean 12/365

                    //    nFraction = yearlyFraction * WorkDays;
                    //}
                    nFraction = 0;
                    if (Global.DateFunctions.DateDiff("m", GlobalFunctions.FirstDateOfMonth(StartDate),
                            GlobalFunctions.LastDateOfMonth(EndDate)) > 2)
                    {
                        nFraction = Global.DateFunctions.DateDiff("m", GlobalFunctions.FirstDateOfMonth(StartDate.AddMonths(1)),
                            GlobalFunctions.LastDateOfMonth(EndDate.AddMonths(-1)));

                        nFraction = nFraction + (Global.DateFunctions.DateDiff("d", StartDate,
                            GlobalFunctions.LastDateOfMonth(StartDate)) + 1) * 0.0328767123;
                        nFraction = nFraction + (Global.DateFunctions.DateDiff("d", GlobalFunctions.FirstDateOfMonth(EndDate),
                            EndDate) + 1) * 0.0328767123;
                    }
                    else
                    {
                        if (StartDate.Month == EndDate.Month && StartDate.Year == EndDate.Year) // if cross two month 
                        {
                            if (StartDate == FirstDateOfMonth(StartDate) && EndDate == LastDateOfMonth(EndDate))
                                nFraction = 1;
                            else
                                nFraction = nFraction + (Global.DateFunctions.DateDiff("d", StartDate,
                                    EndDate) + 1) * 0.0328767123;
                        }
                        else
                        {
                            if (StartDate == FirstDateOfMonth(StartDate) && EndDate == LastDateOfMonth(EndDate))
                                nFraction = 1;
                            else
                                nFraction = nFraction + (Global.DateFunctions.DateDiff("d", StartDate,
                                     GlobalFunctions.LastDateOfMonth(StartDate)) + 1) * 0.0328767123;

                            if (EndDate == LastDateOfMonth(EndDate))
                                nFraction = nFraction + 1;
                            else nFraction = nFraction + (Global.DateFunctions.DateDiff("d", GlobalFunctions.FirstDateOfMonth(EndDate),
                                EndDate) + 1) * 0.0328767123;
                        }
                    }
                    //while (StartDate <= EndDate)
                    //{
                    //    if (StartDate.Day  != 1 )
                    //    {
                    //        nFraction = nFraction + ((double)(Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d",
                    //                GlobalFunctions.FirstDateOfMonth(EndDate), EndDate) + 1)) * 0.0328767123;
                    //    }
                    //    WorkDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d", StartDate,
                    //        GlobalFunctions.LastDateOfMonth(StartDate)) + 1;

                    //    MonDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d",
                    //        GlobalFunctions.FirstDateOfMonth(StartDate),
                    //        GlobalFunctions.LastDateOfMonth(StartDate)) + 1;
                    //    if (StartDate.Month == EndDate.Month && EndDate != GlobalFunctions.LastDateOfMonth(EndDate))
                    //    {
                    //        nFraction = nFraction + ((double) (Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d",
                    //                GlobalFunctions.FirstDateOfMonth(EndDate), EndDate) + 1)) * 0.0328767123;
                    //    }
                    //    TotFract = TotFract + WorkDays / MonDays;
                    //    StartDate = GlobalFunctions.LastDateOfMonth(StartDate).AddDays(1);
                    //}

                    break;
                case enumfractionCalculatinType.ThirtyDaysMonth:

                    WorkDays = Global.DateFunctions.DateDiff("d", StartDate,
                        GlobalFunctions.LastDateOfMonth(StartDate)) + 1;
                    while (StartDate <= EndDate)
                    {
                        WorkDays = Global.DateFunctions.DateDiff("d", StartDate,
                            GlobalFunctions.LastDateOfMonth(StartDate)) + 1;


                        MonDays = Global.DateFunctions.DateDiff("d",
                            GlobalFunctions.FirstDateOfMonth(StartDate), GlobalFunctions.LastDateOfMonth(StartDate)) + 1;

                        int tempDaya = Global.DateFunctions.DateDiff("d", FirstDateOfMonth(StartDate),
                            GlobalFunctions.LastDateOfMonth(StartDate)) + 1;
                        if (tempDaya == 31) WorkDays = WorkDays - 1;
                        else if (tempDaya < 30)
                            if (tempDaya == 28) WorkDays = WorkDays + 2;
                            else WorkDays = WorkDays + 1;

                        MonDays = 30;


                        if (StartDate.Month == EndDate.Month && EndDate != GlobalFunctions.LastDateOfMonth(EndDate))
                        {
                            WorkDays = Global.DateFunctions.DateDiff("d",
                                    GlobalFunctions.FirstDateOfMonth(EndDate), EndDate) + 1;
                            MonDays = 30;
                        }
                        TotFract = TotFract + WorkDays / MonDays;
                        StartDate = GlobalFunctions.LastDateOfMonth(StartDate).AddDays(1);
                    }
                    nFraction = TotFract;
                    break;
                case enumfractionCalculatinType.ThirtyDaysMonthActual:

                    WorkDays = Global.DateFunctions.DateDiff("d", StartDate,
                        GlobalFunctions.LastDateOfMonth(StartDate)) + 1;
                    while (StartDate <= EndDate)
                    {
                        WorkDays = Global.DateFunctions.DateDiff("d", StartDate,
                            GlobalFunctions.LastDateOfMonth(StartDate)) + 1;


                        MonDays = Global.DateFunctions.DateDiff("d",
                            GlobalFunctions.FirstDateOfMonth(StartDate), GlobalFunctions.LastDateOfMonth(StartDate)) + 1;

                        int tempDaya = Global.DateFunctions.DateDiff("d", FirstDateOfMonth(StartDate),
                            GlobalFunctions.LastDateOfMonth(StartDate)) + 1;
                        //if (tempDaya == 31) WorkDays = WorkDays - 1;
                        //else if (tempDaya < 30)
                        //    if (tempDaya == 28) WorkDays = WorkDays + 2;
                        //    else WorkDays = WorkDays + 1;

                        MonDays = 30;


                        if (StartDate.Month == EndDate.Month && EndDate != GlobalFunctions.LastDateOfMonth(EndDate))
                        {
                            WorkDays = Global.DateFunctions.DateDiff("d",
                                    GlobalFunctions.FirstDateOfMonth(EndDate), EndDate) + 1;
                            MonDays = 30;
                        }
                        double temp = WorkDays / MonDays;
                        if (temp > 1) temp = 1;
                        TotFract = TotFract + temp;
                        StartDate = GlobalFunctions.LastDateOfMonth(StartDate).AddDays(1);
                    }
                    nFraction = TotFract;
                    break;
                default:
                    break;
            }
            return nFraction;
        }

        private static int GetRoundOfDigit()
        {
            int RoundofDigit = 2;
            try
            {
                if (RoundofDigit != -1)
                {
                    //####
                    RoundofDigit = GlobalFunctions.defaultConfigVal.roundOfDigit; // ConfigurationManager.GetIntValue("root", "roundofdegit", EnumConfigurationType.Logic);
                    if (RoundofDigit > 4 || RoundofDigit < 0)
                    {
                        RoundofDigit = -1;
                        throw new ServiceException("Round of digit not greater 4 digit. Location: "
                            + "logic-Configuration; Node:Root, Child-Node:RoundOfDegit, Value:" + RoundofDigit.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ServiceException(ex.InnerException.Message);
            }

            return RoundofDigit;
        }
        private static int GetRoundOfDigit(int roundofDigit)
        {
            
            try
            {
                if (roundofDigit > 4 || roundofDigit < 0)
                {
                    roundofDigit = -1;
                    throw new ServiceException("Round of digit not greater 4 digit. Location: "
                        + "logic-Configuration; Node:Root, Child-Node:RoundOfDegit, Value:" + roundofDigit.ToString());
                }
            }
            catch (Exception ex)
            {
                throw new ServiceException(ex.InnerException.Message);
            }

            return roundofDigit;
        }


        public static double GetFractinalOfMonth(DateTime dDate)
        {
            double WorkDays;
            double TotalDays;
            double nFraction = 1;
            WorkDays = Global.DateFunctions.DateDiff("d", dDate,
                GlobalFunctions.LastDateOfMonth(dDate)) + 1;
            //  bool isYearly = ConfigurationManager.GetBoolValue("root", "fractionalcalculationyearly", EnumConfigurationType.Logic);
            enumfractionCalculatinType ntype = getFractionateCalType();
            switch (ntype)
            {
                case enumfractionCalculatinType.Monthly:
                    TotalDays = Global.DateFunctions.DateDiff("d",
                              GlobalFunctions.FirstDateOfMonth(dDate), GlobalFunctions.LastDateOfMonth(dDate)) + 1;
                    nFraction = (WorkDays / TotalDays);
                    break;
                case enumfractionCalculatinType.Yearly:
                    double yearlyFraction = 0.0328767123; // which mean 12/365
                    if (dDate.Day == 1) // if date is first of month, fractionate should be 1
                        nFraction = 1;
                    else
                        nFraction = yearlyFraction * WorkDays;
                    if (nFraction > 1) nFraction = 1; // monthly fraction can't greater 1, 
                    break;
                case enumfractionCalculatinType.ThirtyDaysMonth:
                    if (dDate == LastDateOfMonth(dDate))
                        return 1;
                    else
                    {
                        WorkDays = Global.DateFunctions.DateDiff("d", dDate,
                                 GlobalFunctions.LastDateOfMonth(dDate)) + 1;
                        int tempDaya = Global.DateFunctions.DateDiff("d", FirstDateOfMonth(dDate),
                            GlobalFunctions.LastDateOfMonth(dDate)) + 1;
                        if (tempDaya == 31) WorkDays = WorkDays - 1;
                        else if (tempDaya < 30)
                            if (tempDaya == 28) WorkDays = WorkDays + 2;
                            else WorkDays = WorkDays + 1;
                        TotalDays = 30;
                        //                        TotalDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d",
                        //                            GlobalFunctions.FirstDateOfMonth(dDate), GlobalFunctions.LastDateOfMonth(dDate));
                        nFraction = (WorkDays / TotalDays);
                    }
                    break;
                case enumfractionCalculatinType.ThirtyDaysMonthActual:
                    if (dDate == LastDateOfMonth(dDate))
                        return 1;
                    else
                    {
                        WorkDays = Global.DateFunctions.DateDiff("d", dDate,
                                 GlobalFunctions.LastDateOfMonth(dDate)) + 1;
                        int tempDaya = Global.DateFunctions.DateDiff("d", FirstDateOfMonth(dDate),
                            GlobalFunctions.LastDateOfMonth(dDate)) + 1;
                        //if (tempDaya == 31) WorkDays = WorkDays - 1;
                        //else if (tempDaya < 30)
                        //    if (tempDaya == 28) WorkDays = WorkDays + 2;
                        //    else WorkDays = WorkDays + 1;
                        TotalDays = 30;
                        //                        TotalDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d",
                        //                            GlobalFunctions.FirstDateOfMonth(dDate), GlobalFunctions.LastDateOfMonth(dDate));
                        nFraction = (WorkDays / TotalDays);
                    }
                    break;
                default:
                    break;
            }
            return nFraction;
        }
        public static double GetFractinalOfTillDate(DateTime dDate)
        {
            double WorkDays;
            double TotalDays;
            double nFraction = 1;
            WorkDays = Global.DateFunctions.DateDiff("d",
                GlobalFunctions.FirstDateOfMonth(dDate), dDate) + 1;
            enumfractionCalculatinType ntype = getFractionateCalType();
            switch (ntype)
            {
                case enumfractionCalculatinType.Monthly:
                    TotalDays = Global.DateFunctions.DateDiff("d",
                        GlobalFunctions.FirstDateOfMonth(dDate), GlobalFunctions.LastDateOfMonth(dDate)) + 1;
                    nFraction = (WorkDays / TotalDays);
                    break;
                case enumfractionCalculatinType.Yearly:
                    double yearlyFraction = 0.0328767123; // which mean 12/365
                    if (WorkDays == dDate.Day)
                        nFraction = 1;
                    else
                        nFraction = yearlyFraction * WorkDays;
                    break;
                case enumfractionCalculatinType.ThirtyDaysMonth:
                    if (dDate == FirstDateOfMonth(dDate))
                        return 1;
                    else
                    {
                        WorkDays = Global.DateFunctions.DateDiff("d",
                            GlobalFunctions.FirstDateOfMonth(dDate), dDate) + 1;

                        int tempDaya = Global.DateFunctions.DateDiff("d", FirstDateOfMonth(dDate),
                            GlobalFunctions.LastDateOfMonth(dDate)) + 1;
                        if (tempDaya == 31) WorkDays = WorkDays - 1;
                        else if (tempDaya < 30)
                            if (tempDaya == 28) WorkDays = WorkDays + 2;
                            else WorkDays = WorkDays + 1;

                        TotalDays = 30;
                        //                        TotalDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d",
                        //                            GlobalFunctions.FirstDateOfMonth(dDate), GlobalFunctions.LastDateOfMonth(dDate));
                        nFraction = (WorkDays / TotalDays);
                    }
                    break;
                case enumfractionCalculatinType.ThirtyDaysMonthActual:
                    if (dDate == FirstDateOfMonth(dDate))
                        return 1;
                    else
                    {
                        WorkDays = Global.DateFunctions.DateDiff("d",
                            GlobalFunctions.FirstDateOfMonth(dDate), dDate) + 1;

                        int tempDaya = Global.DateFunctions.DateDiff("d", FirstDateOfMonth(dDate),
                            GlobalFunctions.LastDateOfMonth(dDate)) + 1;
                        //if (tempDaya == 31) WorkDays = WorkDays - 1;
                        //else if (tempDaya < 30)
                        //    if (tempDaya == 28) WorkDays = WorkDays + 2;
                        //    else WorkDays = WorkDays + 1;

                        TotalDays = 30;
                        //                        TotalDays = Ease.CoreV35.Utility.Global.DateFunctions.DateDiff("d",
                        //                            GlobalFunctions.FirstDateOfMonth(dDate), GlobalFunctions.LastDateOfMonth(dDate));
                        nFraction = (WorkDays / TotalDays);
                    }
                    break;
                default:
                    break;
            }
            return nFraction;
        }



        //public static DateTime GetYearEnd()
        //{
        //    object yearEndDate = null;
        //    try
        //    {
        //        yearEndDate = Service.GetYearEndDate();
        //    }
        //    catch (ServiceException e)
        //    {
        //        throw new ServiceException(e.Message, e);
        //    }
        //    return Convert.ToDateTime(yearEndDate);
        //}


        public static DateTime FirstDateOfMonth(DateTime date)
        {
            return Global.DateFunctions.FirstDateOfMonth(date);
        }
        public static string GetShortAttnType(EnumAttendanceType attnType,
            ref int presentDays, ref int absentDays, ref int lateDays,
            ref int leaveDays, ref int weeklyHolidays, ref int osdDays,
            ref int festivalHolidays)
        {
            string type = string.Empty;
            switch (attnType)
            {
                case EnumAttendanceType.Absent:
                    type = "AB";
                    absentDays++;
                    break;

                case EnumAttendanceType.Delay:
                    type = "LP";
                    lateDays++;
                    break;

                case EnumAttendanceType.Holiday:
                    type = "FH";
                    festivalHolidays++;
                    break;

                case EnumAttendanceType.Late:
                    type = "LP";
                    lateDays++;
                    break;

                case EnumAttendanceType.Leave:
                    type = "Lv";
                    leaveDays++;
                    break;

                case EnumAttendanceType.Present:
                    type = "PR";
                    presentDays++;
                    break;


                case EnumAttendanceType.OutSideDuty:
                    type = "OD";
                    osdDays++;
                    break;

                case EnumAttendanceType.Early:
                    type = "E";
                    break;

                case EnumAttendanceType.WeeklyHoliday:
                    type = "WD";
                    weeklyHolidays++;
                    break;
            }
            return type;
        }
        public static string GetLeaveType(int? ReferenceID, List<Leave> _leaves)
        {
            string leaveType = "Lv";
            Leave leave = null;
            if (ReferenceID != 0)
            {
                leave = new Leave();
                leave = _leaves.Where(o => o.ID == ReferenceID).FirstOrDefault();
                if (leave != null)
                {
                    leaveType = leave.Code;
                }
            }

            return leaveType;
        }
        //return Total Hour and Minutes In string Format(Hour.Minutes)
        public static string GetHourMinutes(List<String> hours)
        {
            string HoursMinutes = string.Empty;
            double hour = 0;
            double minutes = 0;
            foreach (String hr in hours)
            {
                //string[] x = hr.ToString("f").Split('.');
                //string xx = hr.ToString();
                if (hr.Contains(":"))
                {
                    hour = hour + Convert.ToDouble(hr.Split(':')[0]);
                    if (hr.Split('.').Length > 1)
                        minutes = minutes + Convert.ToDouble(hr.Split(':')[1]);
                }
                else
                {
                    hour = hour + Convert.ToDouble(hr.Split('.')[0]);
                    if(hr.Split('.').Length >1)
                    minutes = minutes + Convert.ToDouble(hr.Split('.')[1]);
                }

            }

            if (minutes > 60)
            {
                //int hr = Convert.ToInt32(minutes) / 60;
                long hr = Convert.ToInt64(minutes) / 60;
                hour = hour + Convert.ToDouble(hr);
                minutes = minutes % 60;
            }

            return HoursMinutes = Convert.ToString(hour) + ":" + minutes.ToString("00");

        }

        public static string TakaFormat(double _Number)
        {
            //Written by Shaila
            string _sign = "";
            string _NumStr;
            string _TakaFormat;

            if (_Number < 0)
            {
                _sign = "-";
                _Number = (-_Number);
            }

            _NumStr = _Number.ToString("0.00");
            _TakaFormat = Right(_NumStr, 6);
            if ((_NumStr.Length) <= 6)
            {
                _NumStr = "";
            }
            else
                _NumStr = Left(_NumStr, _NumStr.Length - 6);

            if (_NumStr == "")
            {
                _TakaFormat = _sign + _TakaFormat;
                return _TakaFormat;
            }

            int _CommaCount = 1;
            int _DigitCount = 0;

            do
            {
                if (_CommaCount % 3 == 0)
                {
                    _DigitCount = 3;
                }
                else
                    _DigitCount = 2;


                _TakaFormat = Right(_NumStr, _DigitCount) + "," + _TakaFormat;

                if (_NumStr.Length <= _DigitCount)
                {
                    _NumStr = "";
                }
                else
                    _NumStr = Left(_NumStr, _NumStr.Length - _DigitCount);


                _CommaCount = _CommaCount + 1;
            }   //end do
            while (_NumStr != "");
            _TakaFormat = _sign + _TakaFormat;
            return _TakaFormat;

        }	//End of TakaFormat

        public static string Right(string _Str, int _Len)
        {
            //Written by Shaila
            string sStr;

            if (_Len < _Str.Length)
            {
                sStr = _Str.Substring(_Str.Length - _Len, _Len);
            }
            else
                sStr = _Str;
            return sStr;
        }	//EndofRight

        public static string Left(string _Str, int _Len)
        {
            //Written by Shaila
            string sStr;
            if (_Len < _Str.Length)
            {
                sStr = _Str.Substring(0, _Len);
            }
            else
                sStr = _Str;
            return sStr;
        }	//EndofLeft

        public static string GetHourMinutes(double hours)
        {
            var ts = TimeSpan.FromHours(hours);
            return string.Format("{0}:{1}", ts.Hours, ts.Minutes);

        }
        public static DateTime LastPayProcessDate(DateTime nextPayProcessDate)
        {
            return Global.DateFunctions.LastDateOfMonth(nextPayProcessDate.AddMonths(-1));
        }

        public static DateTime LastDateOfMonth(DateTime date)
        {
            return Global.DateFunctions.LastDateOfMonth(date);
        }



        public static String NumWordsWrapper(double value)
        {
            string words = "";
            double intPart;
            double decPart = 0;
            if (value == 0)
                return "zero";

            try
            {
                string[] splitter = value.ToString().Split('.');
                intPart = double.Parse(splitter[0]);
                if (splitter.Length > 1)
                {
                    decPart = double.Parse(splitter[1]);
                }
            }
            catch
            {
                intPart = value;
            }

            words = NumWords(Convert.ToInt32(intPart));

            if (decPart > 0)
            {
                if (words != "")
                    words += " and ";
                int counter = decPart.ToString().Length;
                switch (counter)
                {
                    case 1: words += NumWords(Convert.ToInt32(decPart)) + ""; break;// tenths
                    case 2: words += NumWords(Convert.ToInt32(decPart)) + ""; break;// hundredths
                    case 3: words += NumWords(Convert.ToInt32(decPart)) + ""; break;// thousandths
                    case 4: words += NumWords(Convert.ToInt32(decPart)) + ""; break;// ten-thousandths
                    case 5: words += NumWords(Convert.ToInt32(decPart)) + ""; break;// hundred-thousandths
                    case 6: words += NumWords(Convert.ToInt32(decPart)) + ""; break;// millionths
                    case 7: words += NumWords(Convert.ToInt32(decPart)) + ""; break;// ten-millionths
                }
            }
            return words + " Taka Only";
        }

        private static string NumWords(int Num)
        {
            #region Old Code
            //string[] numbersArr = new string[] { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
            //string[] tensArr = new string[] { "twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninty" };
            //string[] suffixesArr = new string[] { "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", "decillion", "undecillion", "duodecillion", "tredecillion", "Quattuordecillion", "Quindecillion", "Sexdecillion", "Septdecillion", "Octodecillion", "Novemdecillion", "Vigintillion" };
            //string words = "";

            //bool tens = false;

            //if (n < 0)
            //{
            //    words += "negative ";
            //    n *= -1;
            //}

            //int power = (suffixesArr.Length + 1) * 3;

            //while (power > 3)
            //{
            //    double pow = Math.Pow(10, power);
            //    if (n > pow)
            //    {
            //        if (n % Math.Pow(10, power) > 0)
            //        {
            //            words += NumWords(Math.Floor(n / pow)) + " " + suffixesArr[(power / 3) - 1] + " and ";
            //        }
            //        else if (n % pow > 0)
            //        {
            //            words += NumWords(Math.Floor(n / pow)) + " " + suffixesArr[(power / 3) - 1];
            //        }
            //        n %= pow;
            //    }
            //    power -= 3;
            //}
            //if (n >= 1000)
            //{
            //    if (n % 1000 > 0) words += NumWords(Math.Floor(n / 1000)) + " thousand and ";
            //    else words += NumWords(Math.Floor(n / 1000)) + " thousand";
            //    n %= 1000;
            //}
            //if (0 <= n && n <= 999)
            //{
            //    if ((int)n / 100 > 0)
            //    {
            //        words += NumWords(Math.Floor(n / 100)) + " hundred";
            //        n %= 100;
            //    }
            //    if ((int)n / 10 > 1)
            //    {
            //        if (words != "")
            //            words += " ";
            //        words += tensArr[(int)n / 10 - 2];
            //        tens = true;
            //        n %= 10;
            //    }

            //    if (n < 20)
            //    {
            //        if (words != "" && tens == false)
            //            words += " ";
            //        words += (tens ? "-" + numbersArr[(int)n - 1] : numbersArr[(int)n - 1]);
            //        n -= Math.Floor(n);
            //    }
            //}

            //return words;
            #endregion
            string[] Below20 = { "", "One ", "Two ", "Three ", "Four ",
      "Five ", "Six " , "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ",
    "Twelve " , "Thirteen ", "Fourteen ","Fifteen ",
      "Sixteen " , "Seventeen ","Eighteen " , "Nineteen " };
            string[] Below100 = { "", "", "Twenty ", "Thirty ",
      "Forty ", "Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety " };
            string InWords = "";
            if (Num >= 1 && Num < 20)
                InWords += Below20[Num];
            if (Num >= 20 && Num <= 99)
                InWords += Below100[Num / 10] + Below20[Num % 10];
            if (Num >= 100 && Num <= 999)
                InWords += NumWords(Num / 100) + " Hundred " + NumWords(Num % 100);
            if (Num >= 1000 && Num <= 99999)
                InWords += NumWords(Num / 1000) + " Thousand " + NumWords(Num % 1000);
            if (Num >= 100000 && Num <= 9999999)
                InWords += NumWords(Num / 100000) + " Lac " + NumWords(Num % 100000);
            if (Num >= 10000000)
                InWords += NumWords(Num / 10000000) + " Crore " + NumWords(Num % 10000000);

            return InWords;
        }
    }


    #region Interface IGlobalFunctionService

    public interface IGlobalFunctionService
    {
        DateTime GetOperationDate();
        //DateTime GetServerDate();
        //DataTable AvailableUserObject();

        //DateTime GetCurrentDate();

        //DateTime GetYearEndDate();
        DefaultConfigurationValue RefreshServerValue();

    }

    #endregion
}