using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Stone.Class
{
    public class Waiting
    {

        private static BackgroundWorker BackGroundWorkerW = new BackgroundWorker();
        private static WaitingForm frmWaiting;
        private static Form frmChild;
        public static string Text = "صــبر کنـــید ...";



        //events for BackGroundWorkerW
        private static void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            if (BackGroundWorkerW.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            else
            {
                object objChildForm = Activator.CreateInstance(e.Argument as Type);
                frmChild = objChildForm as Form;
                frmChild.ShowDialog();

                //Cancel backgrdwrkr_DoWork for prevent multiple running DoWork
                BackGroundWorkerW.CancelAsync();
            }
        }
        private static void backgrdwrkr_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }
        private static void backgrdwrkr_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 100)
            {
                //Close WaitingForm
                frmWaiting.Close();
                frmWaiting.Dispose();
            }
        }

        //events for BackGroundWorkerWInForm
        private void bgw_DoWorkInForm(object sender, DoWorkEventArgs e)
        {
            // MessageBox.Show("Start  bgw_DoWorkInForm( in another thread!");
            if (BackGroundWorkerWInForm.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            else
            {
                System.Reflection.MethodInfo mi_DoWork = typeMainForm.GetMethod(strDoWorkInForm);
                e.Result = mi_DoWork.Invoke(formMain, null);

                //Cancel backgrdwrkr_DoWork for prevent multiple running DoWork
                BackGroundWorkerWInForm.CancelAsync();
                // MessageBox.Show("Finished CancelAsync()");
            }
        }
        private void backgrdwrkr_RunWorkerCompletedInForm(object sender, RunWorkerCompletedEventArgs e)
        {
            objMain = e.Result;

            if (EnableSplash)
            {
                frmSplash.Close();
                frmSplash.Dispose();
            }
            else
            {
                frmWaiting2.Close();
                frmWaiting2.Dispose();
            }
        }

        public string TextWaiting = "صــبر کنـــید ...";
        private BackgroundWorker BackGroundWorkerWInForm = new BackgroundWorker();
        private WaitingForm frmWaiting2;
        private SplashForm frmSplash;
        private bool EnableSplash { get; set; }
        private Type typeMainForm;
        private string strDoWorkInForm;


        /// <summary>
        ///Sets or Gets Your Main Form
        /// </summary>
        public static Form formMain { get; set; }

        /// <summary>
        ///Sets or Gets Your Main Object 
        /// </summary>
        public static Object objMain { get; set; }

        /// <summary>
        /// Sets or Gets An Array of Objects
        /// </summary>
        public static Object[] objList { get; set; }

        /// <summary>
        /// Sets or Gets Permision to Multiple Click On Main Form.
        /// </summary>
        public static bool MultipleClickIsAllowed { get; set; }

        /// <summary>
        /// This Method creates a type of 
        /// </summary>
        /// <param name="typeClassForm">Your Class Form's Name like this "typeof(Form1)"</param>
        public static void CreateForm(Type typeClassForm)
        {
            CreateForm(typeClassForm, null, null);
        }

        /// <summary>
        /// Passing Object
        /// </summary>
        /// <param name="typeClassForm">ChildForm Type</param>
        /// <param name="_object">Your Object</param>
        public static void CreateForm(Type typeClassForm, Object _object)
        {
            CreateForm(typeClassForm, null, _object, null);
        }

        /// <summary>
        /// Passing Form
        /// </summary>
        /// <param name="typeClassForm">ChildForm Type</param>
        /// <param name="_frmMain">Your Object</param>
        public static void CreateForm(Type typeClassForm, Form _frmMain)
        {
            CreateForm(typeClassForm, _frmMain, null, null);
        }

        /// <summary>
        /// Passing An Array of Object
        /// </summary>
        /// <param name="typeClassForm"></param>
        /// <param name="_objList"></param>
        public static void CreateForm(Type typeClassForm, params object[] _objList)
        {
            CreateForm(typeClassForm, null, null, _objList);
        }

        /// <summary>
        /// Create a ChilForm and Object and Object List and Show it and then Pass MainForm
        /// </summary>
        /// <param name="typeClassForm">ChildForm Type</param>
        /// <param name="_frmMain">MainForm</param>
        /// <param name="_objMain">Object</param>
        /// <param name="_objectList">Object List</param>
        public static void CreateForm(Type typeClassForm, Form _frmMain, Object _objMain, params Object[] _objectList)
        {
            if (MultipleClickIsAllowed && BackGroundWorkerW.IsBusy)
                return;
            else
                BackGroundWorkerW = new BackgroundWorker();

            frmWaiting = new WaitingForm(Text);

            if (_frmMain != null)
                formMain = _frmMain;
            if (_objMain != null)
                objMain = _objMain;
            if (_objectList != null)
            {
                objList = new object[_objectList.Length];
                objList = _objectList;
            }

            BackGroundWorkerW.WorkerSupportsCancellation = true;
            BackGroundWorkerW.WorkerReportsProgress = true;
            BackGroundWorkerW.ProgressChanged += backgrdwrkr_ProgressChanged;
            BackGroundWorkerW.RunWorkerCompleted += backgrdwrkr_RunWorkerCompleted;
            BackGroundWorkerW.DoWork += bgw_DoWork;

            BackGroundWorkerW.RunWorkerAsync(typeClassForm);

            frmWaiting.ShowDialog();

        }

        /// <summary>
        /// Sends a signal that the ChildForm is loaded
        /// </summary>
        public static void ReportCompleted()
        {
            BackGroundWorkerW.ReportProgress(100);
        }

        /// <summary>
        /// Create a WaitingForm In the Main Form
        /// </summary>
        /// <param name="_typeMainForm">Enter typeof(MainForm)</param>
        /// <param name="frm">Enter this</param>
        /// <param name="blEnableSplash">Enable Splash</param>
        /// <param name="blEnableSplash">Enable Splash</param>
        /// <param name="_use_ReportForceCompleteInForm_Method">Use ReportForceCompleteInForm Method</param>
        public object CreateInForm(Type _typeMainForm, Form frm, bool blEnableSplash, bool _use_ReportForceCompleteInForm_Method, string _strDoWorkInForm)
        {
            typeMainForm = _typeMainForm;
            formMain = frm;
            EnableSplash = blEnableSplash;
            strDoWorkInForm = _strDoWorkInForm;
            BackGroundWorkerWInForm = new BackgroundWorker();

            BackGroundWorkerWInForm.WorkerSupportsCancellation = true;

            if (EnableSplash)
                frmSplash = new SplashForm(TextWaiting);
            else
                frmWaiting2 = new WaitingForm(TextWaiting);


            if (!_use_ReportForceCompleteInForm_Method)
                BackGroundWorkerWInForm.RunWorkerCompleted += backgrdwrkr_RunWorkerCompletedInForm;
            else
                BackGroundWorkerWInForm.RunWorkerCompleted -= backgrdwrkr_RunWorkerCompletedInForm;


            BackGroundWorkerWInForm.DoWork += bgw_DoWorkInForm;

            BackGroundWorkerWInForm.RunWorkerAsync();


            //MessageBox.Show("MainThread before Form Waiting");
            if (EnableSplash)
                frmSplash.ShowDialog();
            else
                frmWaiting2.ShowDialog();
            return objMain;
        }

        /// <summary>
        /// Use this when you need to ReportForceCompleteInForm such as web browsers DocumentCompleted  event
        /// </summary>
        public void ReportForceCompleteInForm()
        {
            //Just Waiting
            //MessageBox.Show("Just Waiting Not Splash -- ReportForceCompleteInForm() Invoked!");
            frmWaiting2.Close();
            frmWaiting2.Dispose();
        }
    }
}

