using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using MySQL.Grt;
using MySQL.Utilities;
using MySQL.Grt.Db;

namespace MySQL.GUI.Workbench.Plugins
{
  public partial class DbMysqlRoutineGroupEditor : ObjectEditorPlugin //DockContent//
  {
    #region Member Variables

    private MySQLRoutineGroupEditorBE routineGroupEditorBE { get { return editorBE as MySQLRoutineGroupEditorBE; } } 
    private DragEventArgs lastDropData;

    #endregion

    #region Constructors

    public DbMysqlRoutineGroupEditor(GrtManager GrtManager, GrtValue GrtList)
      : base(new MySQLRoutineGroupEditorBE(GrtManager, GrtList))
    {
      InitializeComponent();

      sqlEd = new SqlEditorHelper(GrtManager, tabPage2, sqlEditorParseLogCallback);

      InitializingControls = true;
      try
      {
        InitFormData();

        CallRefreshFormData();
      }
      finally
      {
        InitializingControls = false;
      }
      routineGroupEditorBE.add_refresh_ui_handler(RefreshFormDataInvoke);
    }

    #endregion

    #region IWorkbenchDocument implementation

    public override UIForm BackendClass 
    {
      get { return routineGroupEditorBE; }
    }

    #endregion

    #region Form implementation

    protected void InitFormData()
    {
      sqlEd.sqlEditor.AllowDrop = true;
      sqlEd.sqlEditor.DragEnter += new DragEventHandler(ddlEditor_DragEnter);
      sqlEd.sqlEditor.DragOver += new DragEventHandler(ddlEditor_DragOver);
      sqlEd.sqlEditor.DragDrop += new DragEventHandler(ddlEditor_DragDrop);

      routineNamesListBox.KeyDown += new KeyEventHandler(routineNamesListBox_KeyDown);

      ContextMenu listboxMenu = new ContextMenu();
      System.Windows.Forms.MenuItem removeItem = new System.Windows.Forms.MenuItem("Remove routine from the group");
      removeItem.Click += new EventHandler(removeItem_Click);
      listboxMenu.MenuItems.Add(removeItem);
      listboxMenu.Popup += new EventHandler(listboxMenu_Popup);
      routineNamesListBox.ContextMenu = listboxMenu;
      routineNamesListBox.AllowDrop = true;

      routineNamesListBox.DragEnter += new DragEventHandler(ddlEditor_DragEnter);
      routineNamesListBox.DragOver += new DragEventHandler(ddlEditor_DragOver);
      routineNamesListBox.DragDrop += new DragEventHandler(ddlEditor_DragDrop);
    }

    protected override void RefreshFormData()
    {
      nameTextBox.Text = routineGroupEditorBE.get_name();
      TabText = nameTextBox.Text;
      commentTextBox.Text = routineGroupEditorBE.get_comment();
      refresh();
    }

    void listboxMenu_Popup(object sender, EventArgs e)
    {
      ((ContextMenu)sender).MenuItems[0].Enabled = routineNamesListBox.SelectedItem != null;
    }

    void removeItem_Click(object sender, EventArgs e)
    {
      if (routineNamesListBox.SelectedItem != null)
      {
        routineGroupEditorBE.delete_routine_with_name(routineNamesListBox.SelectedItem.ToString());
        refresh();
      }
    }

    private void refresh()
    {
      routineNamesListBox.Items.Clear();

      List<String> nameslist = routineGroupEditorBE.get_routines_names();
      foreach (String name in nameslist)
        routineNamesListBox.Items.Add(name);

      //if (!sqlEd.sqlEditor.IsDirty || sqlEd.EditorBE != routineGroupEditorBE)
      {
        sqlEd.SetEditorBackend(routineGroupEditorBE, routineGroupEditorBE.set_routines_sql);
        sqlEd.sqlEditor.SqlText = routineGroupEditorBE.get_routines_sql();
      }
    }

    void routineNamesListBox_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Delete)
      {
        routineGroupEditorBE.delete_routine_with_name(((ListBox)sender).SelectedItem.ToString());
        refresh();
      }
    }

    void ddlEditor_DragDrop(object sender, DragEventArgs e)
    {
      bool has_routines = false;

      List<GrtValue> values = (List<GrtValue>)e.Data.GetData(typeof(List<GrtValue>));
      foreach (GrtValue value in values)
      {
        if (value.is_object_instance_of("db.mysql.Routine"))
        {
          has_routines = true;
          break;
        }
      }

      if (!has_routines)
        return;

      lastDropData = e;
      //!sqlEd.timer.Stop();
      routineGroupEditorBE.set_sql_parser_log_cb(
        new DBObjectEditorBE.VoidStringListDelegate(sqlEditorParseLogCallbackForDragDrop));
      routineGroupEditorBE.set_routines_sql(sqlEd.sqlEditor.Text);
    }

    void ddlEditor_DragOver(object sender, DragEventArgs e)
    {
      e.Effect = DragDropEffects.None;
      if (e.Data.GetDataPresent(typeof(List<GrtValue>)) == true)
      {
        List<GrtValue> values = (List<GrtValue>)e.Data.GetData(typeof(List<GrtValue>));
        bool has_routines = false;
        foreach (GrtValue value in values)
        {
          if (value.is_object_instance_of("db.mysql.Routine"))
          {
            has_routines = true;
            break;
          }
        }
        if(has_routines)
          e.Effect = DragDropEffects.Copy;
      }
    }

    void ddlEditor_DragEnter(object sender, DragEventArgs e)
    {
      ddlEditor_DragOver(sender, e);
    }

    private void sqlEditorParseLogCallbackForDragDrop(List<String> strlist)
    {
      //!sqlEd.timer.Stop();
      routineGroupEditorBE.set_sql_parser_log_cb(
        new DBObjectEditorBE.VoidStringListDelegate(sqlEditorParseLogCallback));

      bool dropPreCheckPassed = !routineGroupEditorBE.has_syntax_error() ||
        (MessageBox.Show("Attention! You have errors in your code that make it impossible to parse it. " +
        "If you continue this operation the code that contains the error will not be parsed and lost. " +
        "Are you sure you want to continue?", "Attention!", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes);

      if (dropPreCheckPassed)
      {
        List<GrtValue> values = (List<GrtValue>)lastDropData.Data.GetData(typeof(List<GrtValue>));
        foreach (GrtValue value in values)
        {
          if (value.is_object_instance_of("db.mysql.Routine"))
          {
            routineGroupEditorBE.append_routine_with_id(value.object_id());
            String name = routineGroupEditorBE.get_routine_name(value.object_id());
            routineNamesListBox.Items.Add(name);
          }
        }
        refresh();
      }

      lastDropData = null;
    }

    private void sqlEditorParseLogCallback(List<String> strlist)
    {
      routineNamesListBox.Items.Clear();

      List<String> nameslist = routineGroupEditorBE.get_routines_names();
      foreach (String name in nameslist)
        routineNamesListBox.Items.Add(name);
    }

    private void nameTextBox_TextChanged(object sender, EventArgs e)
    {
      if (!InitializingControls && !nameTextBox.Text.Equals(routineGroupEditorBE.get_name()))
        routineGroupEditorBE.set_name(nameTextBox.Text);

      TabText = nameTextBox.Text;
    }

    private void commentTextBox_TextChanged(object sender, EventArgs e)
    {
      if (!InitializingControls && !commentTextBox.Text.Equals(routineGroupEditorBE.get_comment()))
        routineGroupEditorBE.set_comment(commentTextBox.Text);
    }

    private void flatTabControl1_SelectedIndexChanged(object sender, EventArgs e)
    {
      if (mainTabControl.SelectedTab == tabPage2)
      {
        if (sqlEd.sqlEditor.Selection.Start == 0)
        {
          // hack to find line 5th line
          int charCount = 0;
          for (int i = 0; i < 5; ++i)
            charCount += sqlEd.sqlEditor.Lines[i].Length + Environment.NewLine.Length;
          sqlEd.sqlEditor.Selection.Start = charCount;
          sqlEd.sqlEditor.Selection.End = charCount;
        }

        sqlEd.sqlEditor.Focus();
      }
    }

    private void DbMysqlRoutineGroupEditor_Load(object sender, EventArgs e)
    {
      ActiveControl = nameTextBox;
    }

    private void pasteProcedureBodyToolStripMenuItem_Click(object sender, EventArgs e)
    {
      sqlEd.sqlEditor.Selection.Text = routineGroupEditorBE.get_procedure_body();
    }

    private void pasteFunctionBodyToolStripMenuItem_Click(object sender, EventArgs e)
    {
      sqlEd.sqlEditor.Selection.Text = routineGroupEditorBE.get_function_body();
    }

    private void undoItem_Click(object sender, EventArgs e)
    {
      sqlEd.sqlEditor.UndoRedo.Undo();
    }

    private void cutItem_Click(object sender, EventArgs e)
    {
      sqlEd.sqlEditor.Clipboard.Cut();
    }

    private void copyItem_Click(object sender, EventArgs e)
    {
      sqlEd.sqlEditor.Clipboard.Copy();
    }

    private void pasteItem_Click(object sender, EventArgs e)
    {
      sqlEd.sqlEditor.Clipboard.Paste();
    }

    private void selectAllItem_Click(object sender, EventArgs e)
    {
      sqlEd.sqlEditor.Selection.SelectAll();
    }

    private void redoItem_Click(object sender, EventArgs e)
    {
      sqlEd.sqlEditor.UndoRedo.Redo();
    }

    private void editorContextMenu_Opening(object sender, CancelEventArgs e)
    {
      // Enable/Disable menu items depending on the edit content.
      undoItem.Enabled = sqlEd.sqlEditor.UndoRedo.CanUndo;
      redoItem.Enabled = sqlEd.sqlEditor.UndoRedo.CanRedo;
      cutItem.Enabled = sqlEd.sqlEditor.Selection.Length > 0;
      copyItem.Enabled = sqlEd.sqlEditor.Selection.Length > 0;
      pasteItem.Enabled = sqlEd.sqlEditor.Clipboard.CanPaste;
      selectAllItem.Enabled = sqlEd.sqlEditor.TextLength > 0;
    }

    #endregion

  }
}