using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;

namespace MySQL.Utilities
{
  public interface ISplashScreen
  {
    void SetSplashScreenStatusInfo(string NewStatusInfo);
  }

  public class MySQLApplicationContext : ApplicationContext
  {
    private static MySQLApplicationContext currentContext;

    public MySQLApplicationContext()
    {
      if (currentContext == null)
        currentContext = this;
    }

    public MySQLApplicationContext(Form AppMainForm)
      : this()
    {
      this.MainForm = AppMainForm;
    }

    public static MySQLApplicationContext CurrentContext
    {
      get { return currentContext; }
    }

    public static string MainFormStatusBarText
    {
      get
      {
        if (currentContext.MainForm is IMySQLMainForm)
          return ((IMySQLMainForm)(currentContext.MainForm)).StatusBarText;
        else
          return "";
      }
      set
      {
        if (currentContext.MainForm is IMySQLMainForm)
          ((IMySQLMainForm)(currentContext.MainForm)).StatusBarText = value;
      }
    }
  }

  public class SplashScreen
  {
    private static Form form = null;
    private static ISplashScreen splashScreenInterface = null;
    private static Thread thread = null;
    private static string tempStatus = string.Empty;

    /// <summary>
    /// Display the splash form
    /// </summary>
    public static void Show(Type splashFormType)
    {
      if (thread != null)
        return;

      if (splashFormType == null)
      {
        throw (new Exception("splashFormType is null"));
      }

      thread = new Thread(new ThreadStart(
        delegate()
        {
          CreateInstance(splashFormType);
          Application.Run(form);
        }));

      thread.IsBackground = true;
      thread.SetApartmentState(ApartmentState.STA);

      thread.Start();
    }



    /// <summary>
    /// Set the status message
    /// </summary>
    public static string Status
    {
      set
      {
        if (splashScreenInterface == null || form == null)
        {
          tempStatus = value;
          return;
        }

        form.Invoke(
            new SplashStatusChangedHandle(
              delegate(string str) 
              { splashScreenInterface.SetSplashScreenStatusInfo(str); }),
            new object[] { value });
      }

    }

    /// <summary>
    /// Close the splashscreen
    /// </summary>
    public static void Close()
    {
      if (thread == null || form == null) 
        return;

      try
      {
        form.Invoke(new MethodInvoker(form.Close));
      }
      catch (Exception)
      {
        // Ignore exceptions at this point
      }

      thread = null;
      form = null;
    }

    private static void CreateInstance(Type FormType)
    {

      object obj = FormType.InvokeMember(null,
        BindingFlags.DeclaredOnly |
        BindingFlags.Public | 
        BindingFlags.NonPublic |
        BindingFlags.Instance | 
        BindingFlags.CreateInstance, null, null, null);

      form = obj as Form;

      splashScreenInterface = obj as ISplashScreen;
      if (form == null || splashScreenInterface == null)
      {
        throw (new Exception(
          "The type passed in must inherit from System.Windows.Forms.Form and must implement the ISplashScreen interface."));
      }

      if (!string.IsNullOrEmpty(tempStatus))
        splashScreenInterface.SetSplashScreenStatusInfo(tempStatus);
    }

    private delegate void SplashStatusChangedHandle(string NewStatusInfo);

  }
}
