/// jcsTree.cpp
/**
*/

#if defined(__WXGTK__) || defined(__WXMOTIF__)
        #include <wx/wx.h>
#endif

#include <wx/wxprec.h>
#include <wx/treectrl.h>
#include <wx/imaglist.h>
#include <wx/string.h>

#include "jcsTree.h"

#include "file.xpm"
#include "folder.xpm"
#include "open_folder.xpm"

jcsTreeCtrl::jcsTreeCtrl(wxWindow* parent, wxWindowID id,
             long style, const char* root) 
: wxTreeCtrl(parent, id, wxDefaultPosition, wxDefaultSize,
        style), mStyle(style)
{
  CreateImageList();
  AddRoot(wxString(root, wxConvLocal), folder_icon, -1, new jcsTreeItemData(root, dtROOT));
  SetItemImage(GetRootItem(), open_folder_icon,
    wxTreeItemIcon_Expanded);
}

void
jcsTreeCtrl::CreateImageList(int size)
{

  wxImageList* images = new wxImageList(size, size, true);

  images->Add(wxIcon(folder_xpm));
  images->Add(wxIcon(open_folder_xpm));
  images->Add(wxIcon(file_xpm));

  AssignImageList(images);

}


///
/**
*/
void
jcsTreeCtrl::Reset()
{
  mTreeMap.clear();

  if (HasVisibleRoot()) { Collapse(GetRootItem()); }

  DeleteChildren(GetRootItem());
}


///
/**
*/
bool
jcsTreeCtrl::HasVisibleRoot()
{
  return (GetFirstVisibleItem().IsOk() && 
    (GetFirstVisibleItem() == GetRootItem()));
}


///
/**
*/
void
jcsTreeCtrl::RemoveBranch(wxTreeItemId branch)
{
  if (branch == GetRootItem()) { return; }
  jcsTreeItemData* item = (jcsTreeItemData*) GetItemData(branch);

  if (item->GetItemType() == dtFILE) { return; }

  wxTreeItemId parent = GetItemParent(branch);
  mRemoveFromMap(branch);
  Delete(branch);

  if (parent != GetRootItem() && !ItemHasChildren(parent)) {
    RemoveBranch(parent);
  }
}


///
/**
*/
// delete items recursively from tree map
void
jcsTreeCtrl::mRemoveFromMap(wxTreeItemId branch)
{
  if (branch != GetRootItem()) {
    jcsTreeItemData* item = (jcsTreeItemData*) GetItemData(branch);
    // remove item's children
    if (ItemHasChildren(branch)) {
      int n_children = GetChildrenCount(branch, false);
      wxTreeItemIdValue cookie;
      wxTreeItemId child = GetFirstChild(branch, cookie);
      mRemoveFromMap(child);
      for (int i = 1; i < n_children; ++i) {
        child = GetNextChild(branch, cookie);
        mRemoveFromMap(child);
      }
    }
  
    // remove item
    mTreeMap.erase(item->GetUid());
  }
}


///
/**
*/
bool
jcsTreeCtrl::IsChild(const wxTreeItemId& item, 
           const wxTreeItemId& parent) const
{
  bool retval = false;
  if (ItemHasChildren(parent)) {
    wxTreeItemIdValue cookie;
    wxTreeItemId child = GetFirstChild(parent, cookie);
    if (item == child || IsChild(item, child)) {
      retval = true;
    }
    else {
      for (unsigned int i = 1; i < GetChildrenCount(item, false); ++i) {
        child = GetNextChild(parent, cookie);
        if (item == child || IsChild(item, child)) {
          retval = true;
          break;
        }
      }
    }
  }
  return retval;
}
  

///
/**
*/
int
jcsTreeCtrl::GetItemType(const wxTreeItemId& item) const
{
  int retval = -1;
  if (item.IsOk()) {
    jcsTreeItemData* data = dynamic_cast<jcsTreeItemData *> (GetItemData(item));
    retval = data->GetItemType();
  }
  return retval;
}


///
/** Returns the type of the selection. If multiple selected
    items are permitted, returns the type of the first
    selected item.
    \return The type of the selection, one of dtROOT,
            dtSUBJECT, dtSTUDY, dtSERIES, dtFILE.
*/
int
jcsTreeCtrl::GetSelectionType() const
{
  wxArrayTreeItemIds selecteds;
  GetSelected(selecteds);
  return GetItemType(selecteds[0]);
}


///
/**
*/
wxString
jcsTreeCtrl::GetStringSelection() const
{
  wxTreeItemId selected;
  wxArrayTreeItemIds selecteds;
  wxString retval;
  GetSelections(selecteds);
  selected = selecteds[0];
  if (selected.IsOk()) {
    retval = GetItemText(selected);
  }
  else {
    retval = _T("error");
  }
  return retval;
}


///
/**
*/
wxString
jcsTreeCtrl::GetStringSelection(const wxTreeItemId& selected) const
{
  wxString retval;
  if (selected.IsOk()) {
    retval = GetItemText(selected);
  }
  else {
    retval = _T("error");
  }
  return retval;
}


///
/**
*/
const std::string
jcsTreeCtrl::GetItemUid(const wxTreeItemId& item) const
{
  if (item.IsOk()) {
    jcsTreeItemData* data =
      static_cast<jcsTreeItemData *> (GetItemData(item));

    return data->GetUid();
  }

  else { return std::string(); }
}

const std::string
jcsTreeCtrl::GetPrefix(const wxTreeItemId& item) const
{
  if (item.IsOk()) {
    jcsTreeItemData* data =
      static_cast<jcsTreeItemData *> (GetItemData(item));

    return data->GetPrefix();
  }

  else return std::string();
}

std::string
jcsTreeCtrl::GetSelectionUid() const
{
  return GetItemUid(GetSelection());
}


wxTreeItemId
jcsTreeCtrl::GetTreeId(std::string uid) const
{
  if (mTreeMap.count(uid)) {
    return (*mTreeMap.find(uid)).second;
  }
  else {
    return GetRootItem();
  }
} 

const std::string
jcsTreeCtrl::GetSeriesUid(const wxTreeItemId& item) const
{
  if (item.IsOk()) {
    jcsTreeItemData* data = static_cast<jcsTreeItemData *> (GetItemData(item));
    return data->GetSeriesUid();
  }
  else { return std::string(); }
}


bool
jcsTreeCtrl::IsMultiple() const
{
  return (mStyle && wxTR_MULTIPLE);
}


///
/** Gets selected tree items
*/
int
jcsTreeCtrl::GetSelected(wxArrayTreeItemIds& selecteds) const
{
  wxTreeItemId selected;
  unsigned int n_selected = 0;
  if (IsMultiple()) {
    n_selected = GetSelections(selecteds);
  }
  else {
    n_selected = 1;
    selecteds.Add(GetSelection());
  }
  return n_selected;
}
