#include "stdafx.h"

#include "wb_overview_workspace.h"
#include "wb_overview_connections.h"
#include "wb_context.h"

using namespace wb;
using namespace bec;


class WorkbenchCentralPlaceholderNode : public OverviewBE::ContainerNode
{
public:
  WorkbenchCentralPlaceholderNode()
  : OverviewBE::ContainerNode(OverviewBE::OSpecial)
  {
    type= OverviewBE::ODivision;
    expanded= true;
    display_mode= OverviewBE::MSmallIcon;

    label= _("Workbench Central");    
  }
  
  virtual std::string get_node_unique_id(const bec::NodeId &node)
  {
    return "wbcentral";
  }
};


class ModelFileNode : public OverviewBE::Node
{
  std::string _path;
public:
  ModelFileNode(const std::string &path)
  : _path(path)
  {
    gchar *p= g_path_get_basename(path.c_str());
    gchar *pp= strrchr(p, '.');
    if (pp) *pp= 0;
    label= p;
    g_free(p);
  }
  
  std::string path() const { return _path; }
  
  virtual bool activate(WBContext *wb)
  {
    // need to make a copy of the path string because opening a document
    // will close the current one, and that may mean this node (holding _path) gets deleted
    wb->open_document(std::string(_path));

    return true;
  }
  
  virtual bool is_deletable() 
  {
    return false;
  }
  
  virtual void delete_object(WBContext *wb)
  {
    
  }
};


class ModelFileListNode : public OverviewBE::ContainerNode
{
  grt::StringListRef _recent_files;
public:
  ModelFileListNode(const grt::StringListRef &files)
  : ContainerNode(OverviewBE::OItem), _recent_files(files)
  {    
    type= OverviewBE::ODivision;
    label= _("Model Files");
    small_icon= 0;
    large_icon= 0;
    expanded= true;
    display_mode= OverviewBE::MLargeIcon;
    
    refresh_children();
  }
  
  static bool compare(const Node *a, const Node *b)
  {
    return a->label < b->label;
  }
  
  virtual void refresh_children()
  {
    clear_children();
    
    for (grt::StringListRef::const_iterator iter= _recent_files.begin();
         iter != _recent_files.end(); ++iter)
    {
      ModelFileNode *node= new ModelFileNode((*iter).c_str());
      
      std::string icon_name= "workbench.Document.$.png";
      node->small_icon= IconManager::get_instance()->get_icon_id(icon_name, Icon16);
      node->large_icon= IconManager::get_instance()->get_icon_id(icon_name, Icon48);
      
      children.push_back(node);
    }

    std::sort(children.begin(), children.end(), compare);
  }
};


class WorkspaceRootNode : public OverviewBE::ContainerNode
{
  WBContext *_wb;
  WorkspaceOverviewBE *_overview;
  
  void option_list_changed(grt::internal::OwnedList *list, bool added, const grt::ValueRef &value,
                           grt::internal::Value *the_list)
  {
    if (_overview && list == the_list)
      _overview->send_refresh_model_files();
  }

  void rdbms_list_changed(grt::internal::OwnedList *list, bool added, const grt::ValueRef &value,
                          grt::internal::Value *the_list)
  {
    if (_overview && list == the_list)
      _overview->send_refresh_connections();
  }

  sigc::connection opt_changed_conn;
  sigc::connection rdbms_changed_conn;  
public:
  virtual ~WorkspaceRootNode()
  {
    opt_changed_conn.disconnect();
    rdbms_changed_conn.disconnect();  
    _wb = 0;
    _overview = 0;
  }

  WorkspaceRootNode(WBContext *wb, WorkspaceOverviewBE *overview)
    : ContainerNode(OverviewBE::ODivision), _wb(wb), _overview(overview)
  {
    type= OverviewBE::ORoot;
    expanded= true;
    display_mode= OverviewBE::MSmallIcon;

    label= _("Overview");

    refresh_children();
  }
  
  
  virtual void refresh_children()
  {
    clear_children();
    children.push_back(new WorkbenchCentralPlaceholderNode());      

    if (_wb)
    {
      children.push_back(new ConnectionListNode(_wb->get_root()->rdbmsMgmt()->storedConns()));
      children.push_back(new ModelFileListNode(_wb->get_root()->options()->recentFiles()));
      
      opt_changed_conn = _wb->get_root()->options()->signal_list_changed().
      connect(sigc::bind(sigc::mem_fun(this, &WorkspaceRootNode::option_list_changed), 
                         _wb->get_root()->options()->recentFiles().valueptr()));
      
      rdbms_changed_conn = _wb->get_root()->rdbmsMgmt()->signal_list_changed().
      connect(sigc::bind(sigc::mem_fun(this, &WorkspaceRootNode::rdbms_list_changed), 
                         _wb->get_root()->rdbmsMgmt()->storedConns().valueptr()));
    }
  }
};


WorkspaceOverviewBE::WorkspaceOverviewBE(WBContext *wb)
  : OverviewBE(wb)
{
  _root_node= new WorkspaceRootNode(0, 0);
}


std::string WorkspaceOverviewBE::identifier() const
{
  return "overview.workspace";
}


std::string WorkspaceOverviewBE::get_form_context_name() const
{
  return WB_CONTEXT_MAIN_OVERVIEW;
}


void WorkspaceOverviewBE::reset(WBContext *wb)
{
  delete _root_node;

  _root_node= new WorkspaceRootNode(_wb, this);
}


void WorkspaceOverviewBE::refresh_node(const bec::NodeId &node_id, bool children)
{
  Node *node= get_node(node_id);
  if ( node )
  {
    node->refresh();
    
    if ( children )
    {
      OverviewBE::ContainerNode* n = dynamic_cast<OverviewBE::ContainerNode*>(node);
      if ( n )
        n->refresh_children();
    }
  }  
}


std::string WorkspaceOverviewBE::get_node_drag_type(const bec::NodeId &node)
{
  if (node.depth() > 0 && node[0] == 2)
    return "file";
  return "";
}


bool WorkspaceOverviewBE::should_accept_file_drop_to_node(const bec::NodeId &node, const std::string &path) 
{
  if (g_str_has_suffix(path.c_str(), ".mwb"))
    return true;
  return false;
}


void WorkspaceOverviewBE::add_file_to_node(const bec::NodeId &node, const std::string &path)
{
  if (_wb->get_root()->options()->recentFiles().get_index(path) == grt::BaseListRef::npos)
    _wb->get_root()->options()->recentFiles().insert(path);
}


std::string WorkspaceOverviewBE::get_file_for_node(const bec::NodeId &node) 
{
  ModelFileNode *n= dynamic_cast<ModelFileNode*>(get_node(node));
  if (n)
    return n->path();
  return "";
}


bool WorkspaceOverviewBE::get_field(const bec::NodeId &node, int column, std::string &value)
{
  static struct {
    const char *label;
    const char *description;
    const char *url;
  } values[]= {
    {"Dev-Central Blogs",
      "Keep up to date and read the latest information about the product and extensions.",
    "http://wb.mysql.com"},
    {"Featured WB Plugins",
      "Browse featured WB Plugins and read on how they can aid your work.",
    ""},
    {"Workbench Tutorials",
      "Browse featured WB Plugins in the Workbench Site.",
      ""},
    {"Forums",
      "Discuss Workbench related topics with other users.",
      ""},
    
    {"Submit Bug Report",
      "",
      "http://bugs.mysql.com/report.php"},
    {"Check for Updates",
      "",
      ""},
    {"Browse Plugins",
      "",
    ""}
  };
  
  // handle workbench central nodes manually
  if (node.depth() == 2 && node[0] == 0)
  {
    int index= -1;
    switch (node[1])
    {
      case 10:
        index= 0;
        break;
      case 11:
        index= 1;
        break;
      case 12:
        index= 2;
        break;
      case 13:
        index= 3;
        break;
      case 100:
        index= 4;
        break;
      case 101:
        index= 5;
        break;
      case 102:
        index= 6;
        break;
    }
    if (index < 0)
      return false;
    switch (column)
    {
      case Label:
        value= values[index].label;
        break;
      case LinkDescription:
        value= values[index].description;
        break;
      case LinkURL:
        value= values[index].url;
        break;
    }
    return true;
  }
  return OverviewBE::get_field(node, column, value);
}


void WorkspaceOverviewBE::send_refresh_connections()
{
  send_refresh_children(bec::NodeId(1));
}


void WorkspaceOverviewBE::send_refresh_model_files()
{
  send_refresh_children(bec::NodeId(2));
}

