public static void PrintPayments(IEnumerable <MonthPayment> monthPayments, bool withPaymentsDetails = false)
        {
            MonthPayment prev           = null;
            bool         todayPrined    = false;
            decimal      totalInterest  = 0;
            decimal      totalPaid      = 0;
            decimal      totalInvest    = 0;
            decimal      totalInvestGrn = 0;

            int mI = 1;
            int pI = 1;

            foreach (var m in monthPayments)
            {
                decimal body     = prev != null ? m.Paid - prev.Interest : 0;
                decimal interest = prev != null ? prev.Interest : 0;
                decimal debt     = m.Debt - body;

                if (m.Date > DateTime.Today && todayPrined == false)
                {
                    Trace.WriteLine("");
                    Trace.WriteLine("For today:");
                    Trace.WriteLine("----------");

                    Trace.WriteLine(string.Format(
                                        "Total paid:\t\t{0,12:0.00}\nTotal body:\t\t{1,12:0.00}\nTotal interest:\t{2,12:0.00}\nTotal invest:\t{3,12:0.00} usd = {4:0.00} uah",
                                        totalPaid, totalPaid - totalInterest, totalInterest, totalInvest, totalInvestGrn));
                    Trace.WriteLine("");
                    todayPrined = true;
                }

                totalInterest  += interest;
                totalPaid      += m.Paid;
                totalInvest    += m.Invest;
                totalInvestGrn += m.InvestGrn;

                string investStr = m.Invest != 0 ? string.Format("invest: {0:0.00} usd, {1:0.00} uah", m.Invest, m.InvestGrn) : "";

                Trace.WriteLine(
                    string.Format(
                        "{0,2} {1,15:MMMM yyyy} {2,12:0.00} {3,9:0.00} {4,9:0.00} {5,9:0.00} {6} {7}",
                        mI++, m.Date, debt, interest, body, m.Paid, m.InvalidCalculation ? "+" : "", investStr));

                if (withPaymentsDetails && m.Payments != null)
                {
                    foreach (var p in m.Payments)
                    {
                        Trace.WriteLine(string.Format("\t\t\t\t\t\t\t{0} {1,15:dd/MM/yyyy} {2,12:0.00} {3}", pI++, p.PaymentDate, p.PayAmount, PrintInvest(p)));
                    }
                }

                prev = m;
            }

            Trace.WriteLine("");
            Trace.WriteLine(string.Format(
                                "Total paid:\t\t{0,12:0.00}\nTotal body:\t\t{1,12:0.00}\nTotal interest:\t{2,12:0.00}\nTotal invest:\t{3,12:0.00} usd = {4:0.00} uah",
                                totalPaid, totalPaid - totalInterest, totalInterest, totalInvest, totalInvestGrn));
        }
        /// <summary>
        /// Calculate mothly payments
        /// </summary>
        /// <param name="payments">payments array</param>
        /// <param name="startDate">first payment date</param>
        /// <param name="debtAmount">debt amount</param>
        /// <param name="withInvest">true - use ivestments during calculation, false - calculate without investments</param>
        /// <returns></returns>
        public MonthPayment[] Calculate(Payment[] payments, DateTime startDate, decimal debtAmount, bool withInvest = true)
        {
            var firstDay = startDate;



            const decimal interestPerHour = 12.7m / (24 * 360 * 100);

            decimal debt = debtAmount;
            var     list = new List <MonthPayment>();

            int          i     = 0;
            MonthPayment prevM = null;

            while (debt > 0 && i < payments.Length)
            {
                var m = new MonthPayment();
                list.Add(m);
                m.Debt = debt;
                m.Date = firstDay;
                DateTime nextMonth = new DateTime(firstDay.Year, firstDay.Month, 1).AddMonths(1);

                if (payments[i].PaymentDate > nextMonth)
                {
                    m.Interest = debt * interestPerHour * (decimal)(nextMonth - firstDay).TotalHours;
                    firstDay   = nextMonth;
                    prevM      = m;
                    continue;
                }
                int j = 0;

                var     paymentsList = new List <Payment>();
                decimal prevInterest = prevM != null ? prevM.Interest : 0;

                decimal invetstMultyplier = withInvest ? 1 : 0;
                while (i < payments.Length && payments[i].PaymentDate < nextMonth)
                {
                    if (payments[i].Interest != null && prevM != null &&
                        Math.Abs(prevM.Difference = (payments[i].Interest.Value - prevM.Interest)) > 0.006m &&
                        prevM.InvalidCalculation == false)
                    {
                        prevM.InvalidCalculation = true;
                    }

                    paymentsList.Add(payments[i].Clone());

                    DateTime beginDate = j == 0 ? firstDay : payments[i - 1].PaymentDateWithShift;

                    m.Interest += debt * interestPerHour * (decimal)(payments[i].PaymentDateWithShift - beginDate).TotalHours;

                    m.Invest    += payments[i].Invest * invetstMultyplier;
                    m.InvestGrn += payments[i].InvestGrn * invetstMultyplier;

                    decimal invest = payments[i].Invest * (invetstMultyplier);

                    decimal payAmount = payments[i].PayAmount + (invest > 0 ? invest : 0);
                    if (payAmount >= prevInterest)
                    {
                        debt        -= (payAmount - prevInterest);
                        prevInterest = 0;
                    }
                    else
                    {
                        prevInterest -= payAmount;
                    }
                    m.Paid += payAmount;
                    i++;
                    j++;
                }
                m.Payments = paymentsList.ToArray();

                m.Interest += debt * interestPerHour * (decimal)(nextMonth - payments[i - 1].PaymentDateWithShift).TotalHours;
                firstDay    = nextMonth;
                prevM       = m;
            }
            return(list.ToArray());
        }