using System;
using System.Collections.Generic;
using System.Windows.Forms;
using MySQL.Grt;
using MySQL.Utilities;
using WeifenLuo.WinFormsUI.Docking;

namespace MySQL.GUI.Shell
{
  class Program
  {
    // The GRT Manager
    private static GrtManager grtManager = null;

    private static GrtShellForm grtShellForm = null;

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] Args)
    {
      // GRT shell variable for easier access
      GrtShell grtShell = null;

      // Parameters
      string modulesPath = ".;./modules";
      string structsPath = "./structs";

      // Command line parsing
      Arguments CommandLine = new Arguments();
      CommandLine.AddOptionName("-modules", false);
      CommandLine.AddOptionName("-structs", false);
      CommandLine.AddOptionName("-verbose", true);
      CommandLine.AddOptionName("-v", true);
      CommandLine.Parse(Args);

      if (CommandLine["modules"] != null)
        modulesPath = CommandLine["modules"];

      if (CommandLine["structs"] != null)
        structsPath = CommandLine["structs"];


      // Try to instantiate the GRT Manager and catch exceptions
      try
      {
        // Create the GRT Manager instance
        grtManager = new GrtManager(true, (CommandLine["verbose"] != null || CommandLine["v"] != null));
        grtShell = grtManager.get_shell();
      }
      catch (Exception ex)
      {
        MessageBox.Show(string.Format("Cannot create GRT Manager.\n\n({0})",
	        ex.Message), "MySQL Grt");
      }

      // If the GRT Manager was successfully created, initialize the application
      if (grtManager != null && grtShell != null)
      {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        // Create the GRT Shell form
        grtShellForm = new GrtShellForm(grtManager);
        grtShellForm.ScriptFilePath = System.IO.Path.Combine(System.IO.Path.Combine(
          System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
          "MySQL"), "Workbench"), "modules");
        ShellContainer container = new ShellContainer();
        grtShellForm.NewShellDocument += new NewShellDocument(container.grtShellForm_NewShellDocument);

        try
        {
          // Set GRT callbacks
          grtManager.set_shell_output_callback(new GrtManager.VoidStringDelegate(grtShellForm.PrintShellOutput));
          grtManager.set_output_callback(new GrtManager.VoidStringDelegate(grtShellForm.PrintShellOutput));
          grtManager.set_error_callback(new GrtManager.VoidStringStringDelegate(grtShellForm.ErrorCallback));
          //grtManager.set_message_callback(new ManagedGRTManager.VoidStringStringDelegate(MessageCallback));
          //grtManager.set_progress_callback(new ManagedGRTManager.VoidStringStringFloatDelegate(ProgressCallback));

          // Set allowed module extensions.
          List<String> extensions = new List<string>();
          extensions.Add(".wb.be");
          extensions.Add(".grt");
          grtManager.set_module_extensions(extensions);

          // Set GRT Shell callbacks
          grtShell.set_ready_handler(new GrtShell.VoidStringDelegate(grtShellForm.PrepareNextCommand));

          // Set shell save directory and restore history
          grtShell.set_save_directory(System.IO.Path.Combine(System.IO.Path.Combine(
              Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
              "MySQL"), "GRT Shell"));
          grtShell.restore_history();

          // Initialize the GRT
          grtManager.set_search_paths(modulesPath, structsPath, "");
          grtManager.initialize();
          grtManager.get_shell().start();

          // Initialize the ShellForm
          grtShellForm.Initialize();

          // Trigger GRT idle tasks
          grtManager.perform_idle_tasks();
        }
        catch (Exception ex)
        {
	        MessageBox.Show(string.Format("Cannot initialize GRT Manager.\n\n({0})",
		        ex.Message), "MySQL Grt");
        }

        // Set the Application.Idle event handler
        Application.Idle += new EventHandler(OnApplicationIdle);

        // Start the Application
        Application.Run(grtShellForm);

        // After the application has run
        if (grtManager != null && grtShell != null)
        {
	        // Store shell history
	        grtShell.store_history();
        }
      }
    }

    private static void OnApplicationIdle(object sender, EventArgs e)
    {
      // Whenever the application is idle, check if there are GRT tasks to be executed
      if (grtManager != null)
      {
        if (grtManager.terminated())
          grtShellForm.Close();

        grtManager.perform_idle_tasks();
      }
    }

    public class ShellContainer
    {
      public bool grtShellForm_NewShellDocument(DockContent documentForm)
      {
        documentForm.Show();
        return true;
      }
    }
  }
}