/*

  xmunipack - archive & tools tree


  Copyright © 2010-2011 F.Hroch (hroch@physics.muni.cz)

  This file is part of Munipack.

  Munipack is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  Munipack is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with Munipack.  If not, see <http://www.gnu.org/licenses/>.

*/


#include "xmunipack.h"
#include <wx/wx.h>
#include <wx/treectrl.h>
#include <wx/stdpaths.h>
#include <wx/dir.h>
#include <wx/filesys.h>
#include <cstdlib>
#include <ctime>

class xTreeItemData: public wxTreeItemData
{
public:
  xTreeItemData(const wxString& d): cdir(d) {}
  wxString cdir;
};

BEGIN_EVENT_TABLE(MuniCollector, wxTreeCtrl)
EVT_TREE_SEL_CHANGED(wxID_ANY, MuniCollector::OnSelChanged)
EVT_TREE_ITEM_ACTIVATED(wxID_ANY, MuniCollector::OnSelChanged)
EVT_TREE_ITEM_MENU(wxID_ANY, MuniCollector::OnItemMenu)
EVT_TREE_BEGIN_LABEL_EDIT(wxID_ANY, MuniCollector::OnEditBegin)
EVT_TREE_END_LABEL_EDIT(wxID_ANY, MuniCollector::OnEditEnd)
EVT_MENU(wxID_EDIT, MuniCollector::OnEdit)
EVT_MENU(wxID_ADD, MuniCollector::OnNewArchive)
EVT_MENU(wxID_REMOVE, MuniCollector::OnExcludeArchive)
END_EVENT_TABLE()


// -----  MuniCollector

MuniCollector::MuniCollector(wxWindow *w):
wxTreeCtrl(w,wxID_ANY,wxDefaultPosition,wxDefaultSize,
	   wxTR_DEFAULT_STYLE|wxTR_HIDE_ROOT|wxTR_FULL_ROW_HIGHLIGHT),
  handevt(w->GetParent()),archive(0)
{
  SetIndent(7);

  int isize = 24;
  MuniArtIcons icons(wxART_FRAME_ICON,wxSize(isize,isize));
  wxImageList *ilist = new wxImageList(isize,isize,false,0);
  ilist->Add(icons.Icon(wxART_FOLDER));
  ilist->Add(icons.Icon(wxART_QUESTION));
  ilist->Add(icons.Icon(wxART_INFORMATION));
  ilist->Add(icons.Icon(wxART_EXECUTABLE_FILE));
  AssignImageList(ilist);

  wxTreeItemId top = AddRoot(wxEmptyString);

  // recursive fill data tree
  arch = AppendItem(top,"Data");
  SetItemBold(arch);

  // add tools
  wxTreeItemId tools = AppendItem(top,"Tools");
  SetItemBold(tools);
  AppendItem(tools,"Average",3);
  AppendItem(tools,"Correction",3);
  Expand(tools);
}

bool MuniCollector::IsOk() const
{
  return archive != 0;
}

void MuniCollector::SetArchive(MuniArchive *a)
{
  archive = a;
  CreateTree(arch);
  wxASSERT(workplace.IsOk());
  SelectItem(workplace);
}

void MuniCollector::OnSelChanged(wxTreeEvent& event) 
{

  current = event.GetItem();
  xTreeItemData *data = static_cast<xTreeItemData *>(GetItemData(current));

  if( data ) {
    archive->ChangeDir(data->cdir);
    last = current;
  }

  event.SetString(GetItemText(event.GetItem()));
  wxQueueEvent(handevt,event.Clone());
}

void MuniCollector::OnItemMenu(wxTreeEvent& event) 
{
  wxLogDebug("MuniCollector::OnItemMenu");

  if( event.GetItem() == event.GetOldItem() )
    {wxLogDebug("MuniCollector::OnItemMenu ==");}


  current = event.GetItem();
  xTreeItemData *item = dynamic_cast<xTreeItemData *>(GetItemData(current));

  if( ! item ) return;

  archive->ChangeDir(item->cdir);

  wxMenu popup;
  popup.Append(wxID_ADD);
  popup.Append(wxID_REMOVE);
  popup.Append(wxID_OPEN);
  popup.Append(wxID_SAVEAS);
  popup.Append(wxID_EDIT,"Rename ...");

  bool enable = ! archive->IsReadOnly();
  popup.Enable(wxID_ADD,enable);
  popup.Enable(wxID_REMOVE,enable);
  popup.Enable(wxID_EDIT,enable);
  popup.Enable(wxID_SAVEAS,false);

  PopupMenu(&popup);
}

void MuniCollector::OnNewArchive(wxCommandEvent& event) 
{
  xTreeItemData *item = dynamic_cast<xTreeItemData *>(GetItemData(current));
  wxASSERT(item);
  const wxString label = "Shelf"; // or drawler ?
  int idx = 0;

  // look for already presented label item
  wxTreeItemIdValue cookie;
  wxTreeItemId t = GetFirstChild(current,cookie);
  while(t.IsOk()){
    wxString l(GetItemText(t));
    if( l.StartsWith(label) )
      idx++;
    t = GetNextChild(current,cookie);
  }

  // add a number to distinguish shelfs
  wxString xlabel(label);
  if( idx > 0 ) {
    wxString x;
    x.Printf("%d",(int) idx);
    xlabel += x;
  }

  archive->ChangeDir(item->cdir);
  archive->MakeDir(xlabel);
  archive->ChangeDir(xlabel);
  
  wxTreeItemId i = AppendItem(current,xlabel,0,-1,
			      new xTreeItemData(archive->GetAbsPath()));
  Expand(current);
  EditLabel(i);
}

void MuniCollector::OnExcludeArchive(wxCommandEvent& event) 
{

  xTreeItemData *item = dynamic_cast<xTreeItemData *>(GetItemData(current));
  wxASSERT(item);
  archive->DeleteDir(item->cdir);
  Delete(current);
}

void MuniCollector::OnEdit(wxCommandEvent& event) 
{
  EditLabel(current);
}

void MuniCollector::OnEditBegin(wxTreeEvent& event) 
{
  if( archive->IsReadOnly() ) {
    event.Veto();
    return;
  }

  origlabel = GetItemText(event.GetItem());
}


void MuniCollector::OnEditEnd(wxTreeEvent& event) 
{

  const wxTreeItemId itemId = event.GetItem();
  xTreeItemData *item = dynamic_cast<xTreeItemData *>(GetItemData(itemId));
  wxASSERT(item);

  if( event.IsEditCancelled() )
    SetItemText(itemId,origlabel);
  else {
    wxLogDebug("MuniCollector::OnEditEnd "+event.GetLabel()+" "+
	       item->cdir+" "+origlabel);
    archive->RenameDir(item->cdir,event.GetLabel());
    item->cdir = archive->GetAbsPath();
    wxLogDebug("MuniCollector::OnEditEnd "+archive->GetAbsPath());
  }
}

void MuniCollector::CreateTree(const wxTreeItemId& parent)
{
  wxASSERT(archive);

  wxTreeItemId item;
  
  wxArrayString labels = archive->GetDirs();

  for(size_t i = 0; i < labels.GetCount(); i++) {
    wxLogDebug("MuniCollector::CreateTree "+labels[i]);
    archive->ChangeDir(labels[i]);

    item = AppendItem(parent,labels[i],0,-1,
		      new xTreeItemData(archive->GetAbsPath()));
    wxLogDebug(archive->GetAbsPath());
    if( labels[i] == "Workplace" )
      workplace = item;
    CreateTree(item);

    archive->ChangeDir("..");
  }
}

void MuniCollector::SelectLastItem()
{
  SelectItem(last);
} 
