using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.IO;
using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
using MySQL.Grt;
using MySQL.GUI.Shell.Properties;

namespace MySQL.GUI.Shell
{
  public class GrtFilesTreeModel : ITreeModel
  {
    /// <summary>
    /// The top node if any, otherwise null
    /// </summary>
    protected GrtTreeNode topNode = null;

		/// <summary>
		/// Constructor that initializes the model with the given objects
		/// </summary>
		/// <param name="TreeView">The TreeViewAdv control this model belongs to</param>
    public GrtFilesTreeModel(TreeViewAdv TreeView)
		{
		}

		/// <summary>
		/// Returns a node list of all child nodes of a given parent node
		/// </summary>
		/// <param name="treePath">The path of the parent node</param>
		/// <returns>The list of child nodes for the given parent path node</returns>
    public System.Collections.IEnumerable GetChildren(TreePath treePath)
    {
      List<Node> items = new List<Node>();

      if (treePath.IsEmpty())
      {
        Node node;

        node = new Node("User Scripts");
        node.Tag = System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(
              Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
              "MySQL"), "Workbench"), "scripts");
        items.Add(node);

        node = new Node("User Modules");
        node.Tag = System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(
              Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
              "MySQL"), "Workbench"), "modules");
        items.Add(node);

        node = new Node("User Libraries");
        node.Tag = System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(
              Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
              "MySQL"), "Workbench"), "libraries");
        items.Add(node);

        node = new Node("Standard Modules");
        System.Reflection.Assembly asm = System.Reflection.Assembly.GetEntryAssembly();
        node.Tag = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(asm.Location),
          "modules");

        items.Add(node);
      }
      else
      {
        try
        {
          Node parent = treePath.LastNode as Node;

          foreach (string filePath in Directory.GetFiles(parent.Tag as string))
          {
            Node node = new Node(new FileInfo(filePath).Name);
            node.Tag = filePath;

            items.Add(node);
          }
        }
        catch (IOException)
        {
          return null;
        }
      }

      return items;
    }

    public bool IsLeaf(TreePath treePath)
    {
      if (treePath.FirstNode == treePath.LastNode)
        return false;
      else
        return true;
    }

    public void RefreshModel()
    {
      OnStructureChanged(new TreePathEventArgs());
    }

    #region Events
    public event EventHandler<TreeModelEventArgs> NodesChanged;
    internal void OnNodesChanged(TreeModelEventArgs args)
    {
      if (NodesChanged != null)
        NodesChanged(this, args);
    }

    public event EventHandler<TreePathEventArgs> StructureChanged;
    public void OnStructureChanged(TreePathEventArgs args)
    {
      if (StructureChanged != null)
        StructureChanged(this, args);
    }

    public event EventHandler<TreeModelEventArgs> NodesInserted;
    internal void OnNodeInserted(Node parent, int index, Node node)
    {
      if (NodesInserted != null)
      {
        TreeModelEventArgs args = new TreeModelEventArgs(GetPath(parent), new int[] { index }, new object[] { node });
        NodesInserted(this, args);
      }
    }

    public event EventHandler<TreeModelEventArgs> NodesRemoved;
    internal void OnNodeRemoved(Node parent, int index, Node node)
    {
      if (NodesRemoved != null)
      {
        TreeModelEventArgs args = new TreeModelEventArgs(GetPath(parent), new int[] { index }, new object[] { node });
        NodesRemoved(this, args);
      }
    }

    /// <summary>
    /// Returns the path of the given node
    /// </summary>
    /// <param name="node">Node of interest</param>
    /// <returns>The path to the given node</returns>
    public virtual TreePath GetPath(Node node)
    {
      if (node == topNode)
        return TreePath.Empty;
      else
      {
        Stack<object> stack = new Stack<object>();
        while (node != topNode)
        {
          stack.Push(node);
          node = node.Parent;
        }
        return new TreePath(stack.ToArray());
      }
    }
    #endregion
  }
}
