using System;
using System.Text;

namespace AddisonWesley.Michaelis.EssentialCSharp.Shared
{
    public partial class PiCalculator
    {
        const int Digits = 100;
        #region Helper
        public static string Pi()
        {
            return Calculate();
        }

        public static string Calculate(int digits = 100)
        {
            return Calculate(digits, 0);
        }

        public static string Calculate(int digits, int startingAt)
        {
            DoWorkEventArgs eventArgs = new DoWorkEventArgs(digits);

            CalculatePi(typeof(PiCalculator), eventArgs, startingAt);
            return (string)eventArgs.Result;
        }

        private static void CalculatePi(
            object sender, DoWorkEventArgs eventArgs)
        {
            CalculatePi(sender, eventArgs, 0);
        }

        private static void CalculatePi(
            object sender, DoWorkEventArgs eventArgs, int startingAt)
        {
            int digits = (int)eventArgs.Argument;

            StringBuilder pi;
            if(startingAt == 0)
            {
                pi = new StringBuilder("3.", digits + 2);
            }
            else
            {
                pi = new StringBuilder();
            }
#if BackgroundWorkerThread
            calculationWorker.ReportProgress(0, pi.ToString());
#endif

            // Obliczanie reszty liczby pi, jeśli to konieczne.
            if(digits > 0)
            {
                for(int i = 0; i < digits; i += 9)
                {

                    // Obliczanie następnych i miejsc po przecinku.
                    int nextDigit = InternalPiDigitCalculator.ComputeSection(
                        startingAt + i + 1);
                    int digitCount = Math.Min(digits - i, 9);
                    string ds = string.Format("{0:D9}", nextDigit);
                    pi.Append(ds.Substring(0, digitCount));

                    // Wyświetlanie aktualnych postępów.
#if BackgroundWorkerThread
                    calculationWorker.ReportProgress(
                        0, ds.Substring(0, digitCount));
#endif

#if BackgroundWorkerThread
                    // Sprawdzanie, czy nie anulowano zadania.
                    if (calculationWorker.CancellationPending)
                    {
                        // Trzeba ustawić pole Cancel, jeśli chcesz sprawdzać,
                        // jak wątek roboczy zakończył pracę 
                        // (np. sprawdzając pole
                        // RunWorkerCompletedEventArgs.Cancelled).
                        eventArgs.Cancel = true;
                        break;
                    }
#endif
                }
            }

            eventArgs.Result = pi.ToString();
        }
        #endregion
    }
}
