/***************************************************************************
 *   Copyright (C) 2005 by Thierry CHARLES   *
 *   thierry@les-charles.net   *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "paths_cfg.h"

#include <wx/dir.h>
#include <wx/dirdlg.h>

#include "components/framework/tapplication.h"
#include "components/framework/tapplicationpanel.h"
#include "components/stdgui/tbitmap.h"
#include "xpe_components/res_id.h"
#include "xpe_components/lib/pathres.h"
#include "lib/lib_file.h"

#include "xpe.h"

#include "bmp_id.h"

void invertElts(TListCtrl * ctrl, int iElt1, int iElt2);

PathsConfigPanelElement::PathsConfigPanelElement(TApplicationPanel * _owner, int iID)
    :TConfigPanelElement(_owner, (iID < 0) ? static_cast<XPE *>(CurrentApplication())->getUPEID() : iID),
    contentPanel(NULL),
    reinitBtn(NULL),
    pathsLabel(NULL),
    pathsList(NULL),
    imagesList(12,12),
    addBtn(NULL),
    upBtn(NULL),
    downBtn(NULL),
    removeBtn(NULL)
{
    this->setName(wxTr("Includes"));
}

void PathsConfigPanelElement::buttonActivated(TGenButton * btn)
{
    if(btn == this->reinitBtn)
    {
        this->init();
    }
    else if(btn == this->addBtn)
    {
        wxDirDialog * dlg = new wxDirDialog(dynamic_cast<wxWindow *>(this->getOwner()->getOwner()), wxTr("Choose a directory containing includes"), wxT(""), (wxDD_DEFAULT_STYLE^wxDD_NEW_DIR_BUTTON));
        int iRes = dlg->ShowModal();
        if(iRes == wxID_OK)
        {
            this->addPath(true,PathsListRes::normalizePath(dlg->GetPath()));
        }
        delete dlg;
    }
    else if(btn == this->upBtn)
    {
        if(!this->pathsList->GetSelectedItemCount())
            return;

        long iSelItem = this->pathsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
        if(iSelItem <= 0)
            return;
        long iAboveItem = iSelItem - 1;
        if(iAboveItem < 0)
            return;

        invertElts(this->pathsList,iSelItem,iAboveItem);
    }
    else if(btn == this->downBtn)
    {
        if(!this->pathsList->GetSelectedItemCount())
            return;

        long iSelItem = this->pathsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
        if(iSelItem < 0 || iSelItem == (this->pathsList->GetItemCount()-1))
            return;
        long iBelowItem = iSelItem + 1;
        if(iBelowItem < 0)
            return;

        invertElts(this->pathsList,iSelItem,iBelowItem);
    }
    else if(btn == this->removeBtn)
    {
        if(!this->pathsList->GetSelectedItemCount())
            return;

        long iSelItem = this->pathsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
        if(iSelItem < 0)
            return;

        this->pathsList->DeleteItem(iSelItem);
    }
}

void PathsConfigPanelElement::addPath(bool bActive, const wxString & sPath)
{
    wxListItem info;
    for(int i = 0 ; i < this->pathsList->GetItemCount() ; i++)
    {
        info.SetId(i);
        info.SetColumn(1);
        info.SetMask(wxLIST_MASK_TEXT);
        this->pathsList->GetItem(info);
        if(info.GetText() == sPath)
        {
            info.SetColumn(0);
            info.SetMask(wxLIST_MASK_IMAGE);
            this->pathsList->GetItem(info);
            info.SetImage(bActive ? 0 : -1);
            info.SetState(wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
            info.SetMask(wxLIST_MASK_IMAGE);
            this->pathsList->SetItem(info);
            return;
        }
    }

    long iItemId = this->pathsList->InsertItem(0, bActive ? 0 : -1);
    info.SetId(iItemId);
    info.SetColumn(1);
    info.SetText(sPath);
    info.SetMask(wxLIST_MASK_TEXT);
    this->pathsList->SetItem(info);
}

/** initialise le panneau avec les parametres actuels de l'application */
void PathsConfigPanelElement::init()
{
    this->pathsList->DeleteAllItems();
    PathsListRes * paths = static_cast<PathsListRes *>(CurrentApplication()->getRessource(PATHS_LIST_RESSOURCE_ID));
    if(paths)
    {
        PathsListRes::TPathsList list = paths->getPathsList();
        PathsListRes::TPathsList::const_iterator it = list.begin();
        while(it != list.end())
        {
            this->addPath((*it).bActive,(*it).sPath);
            it++;
        }
    }
}

/** valide les modifications */
void PathsConfigPanelElement::commit()
{
    PathsListRes * paths = static_cast<PathsListRes *>(CurrentApplication()->getRessource(PATHS_LIST_RESSOURCE_ID));
    if(!paths)
    {
        paths = new PathsListRes();
        CurrentApplication()->publishRessource(PATHS_LIST_RESSOURCE_ID,paths);
    }

    paths->clear();
    wxListItem info;
    for(int i = 0 ; i < this->pathsList->GetItemCount() ; i++)
    {
        info.SetId(i);
        info.SetColumn(0);
        info.SetMask(wxLIST_MASK_IMAGE);
        if(!this->pathsList->GetItem(info))
            continue;
        bool bActive = info.GetImage() == 0;
        info.SetColumn(1);
        info.SetMask(wxLIST_MASK_TEXT);
        if(!this->pathsList->GetItem(info))
            continue;
        wxString sPath = info.GetText();
        paths->addPath(sPath,bActive,i);
    }
}

/** indique si le panneau est dans un état valide */
bool PathsConfigPanelElement::canCommit()
{
    return true;
}

/** construit le panneau conteneur et son contenu (appellé automatiquement par getContentPanel et détruit automatiquement par le destructeur) */
TPanel * PathsConfigPanelElement::buildContentPanel()
{
    if(this->contentPanel)
        return this->contentPanel;

    this->contentPanel = new TPanel(dynamic_cast<wxWindow *>(this->getOwner()->getOwner()));
    wxBoxSizer * mainSizer = new wxBoxSizer( wxVERTICAL);
    contentPanel->SetSizer(mainSizer);

    mainSizer->AddSpacer(5);

    this->reinitBtn = new TGenButton(this->contentPanel);
    this->reinitBtn->setBitmap( GET_BMP(BMP_REFRESH_ID) );
    this->reinitBtn->setText(wxTr("Reload"));
    this->reinitBtn->addButtonListener( this );
    mainSizer->Add(this->reinitBtn,0,wxALIGN_RIGHT|wxLEFT|wxRIGHT,5);

    wxStaticText * label = new wxStaticText(this->contentPanel,-1,wxTr("Includes' paths :"));
    mainSizer->Add(label,0,wxEXPAND|wxLEFT|wxRIGHT,5);

    mainSizer->AddSpacer(3);

    TPanel * panel = new TPanel(this->contentPanel);
    wxBoxSizer * sizer = new wxBoxSizer( wxHORIZONTAL );
    this->pathsList = new TListCtrl(panel, -1, wxDefaultPosition, wxDefaultSize,
                                     wxLC_REPORT | wxLC_SINGLE_SEL | wxSUNKEN_BORDER );
//    this->pathsList->SetImageList(&this->imagesList,wxIMAGE_LIST_SMALL);
    sizer->Add(this->pathsList,1,wxEXPAND);
    sizer->AddSpacer(3);

    // entetes des colonnes (cachées)
    wxListItem itemCol;
    itemCol.SetText(wxTr("Active"));
    itemCol.SetImage(-1);
    this->pathsList->InsertColumn(0, itemCol);

    itemCol.SetText(wxTr("Path"));
    itemCol.SetImage(-1);
    this->pathsList->InsertColumn(1, itemCol);

    this->pathsList->Connect(wxEVT_SIZE,wxSizeEventHandler(PathsConfigPanelElement::onListViewSize), NULL, this);
    this->pathsList->Connect(wxEVT_COMMAND_LIST_ITEM_ACTIVATED,wxListEventHandler(PathsConfigPanelElement::onListViewActivated), NULL, this);

    this->imagesList.RemoveAll();
    this->imagesList.Add(*(GET_BMP(BMP_CHECK_ID)));
    this->pathsList->SetImageList(&this->imagesList,wxIMAGE_LIST_SMALL);

    TPanel * btnsPanel = new TPanel(panel);
    wxBoxSizer * btnsSizer = new wxBoxSizer( wxVERTICAL );

    btnsSizer->AddStretchSpacer(1);

    this->addBtn = new TGenButton(btnsPanel);
    this->addBtn->setBitmap( GET_BMP(BMP_ADD_ID) );
    this->addBtn->addButtonListener( this );
    btnsSizer->Add(this->addBtn,0,wxEXPAND);

    btnsSizer->AddSpacer(5);

    this->upBtn = new TGenButton(btnsPanel);
    this->upBtn->setBitmap( GET_BMP(BMP_UP_ID) );
    this->upBtn->addButtonListener( this );
    btnsSizer->Add(this->upBtn,0,wxEXPAND);

    btnsSizer->AddSpacer(5);

    this->downBtn = new TGenButton(btnsPanel);
    this->downBtn->setBitmap( GET_BMP(BMP_DOWN_ID) );
    this->downBtn->addButtonListener( this );
    btnsSizer->Add(this->downBtn,0,wxEXPAND);

    btnsSizer->AddSpacer(5);

    this->removeBtn = new TGenButton(btnsPanel);
    this->removeBtn->setBitmap( GET_BMP(BMP_REMOVE_ID) );
    this->removeBtn->addButtonListener( this );
    btnsSizer->Add(this->removeBtn,0,wxEXPAND);

    btnsSizer->AddStretchSpacer(1);

    btnsPanel->SetSizer(btnsSizer);
    sizer->Add(btnsPanel,0,wxEXPAND);

    panel->SetSizer(sizer);
    mainSizer->Add(panel,1,wxEXPAND|wxLEFT|wxRIGHT,5);

    return this->contentPanel;
}

void PathsConfigPanelElement::onListViewSize(wxSizeEvent & evt)
{
    evt.Skip();
    if(this->pathsList && this->pathsList->GetClientSize().GetWidth()>0)
    {
        this->pathsList->SetColumnWidth( 0, 50 );
        this->pathsList->SetColumnWidth( 1, this->pathsList->GetClientSize().GetWidth() - 50 - 2 );
    }
}

void PathsConfigPanelElement::onListViewActivated(wxListEvent & evt)
{
    if(!this->pathsList->GetSelectedItemCount())
        return;

    long iSelItem = this->pathsList->GetNextItem(-1,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED);
    if(iSelItem < 0)
        return;

    wxListItem info;
    info.SetId(iSelItem);
    info.SetColumn(0);
    info.SetMask(wxLIST_MASK_IMAGE);
    this->pathsList->GetItem(info);
    info.SetImage(info.GetImage() < 0 ? 0 : -1);
    this->pathsList->SetItem(info);
}

void invertElts(TListCtrl * ctrl, int iElt1, int iElt2)
{
    wxListItem info;

    info.SetId(iElt1);
    info.SetColumn(1);
    info.SetMask(wxLIST_MASK_TEXT);
    ctrl->GetItem(info);
    wxString elt1Txt = info.GetText();
    info.SetColumn(0);
    info.SetMask(wxLIST_MASK_IMAGE);
    ctrl->GetItem(info);
    int elt1Img = info.GetImage();

    info.SetId(iElt2);
    info.SetColumn(1);
    info.SetMask(wxLIST_MASK_TEXT);
    ctrl->GetItem(info);
    wxString elt2Txt = info.GetText();
    info.SetColumn(0);
    info.SetMask(wxLIST_MASK_IMAGE);
    ctrl->GetItem(info);
    int elt2Img = info.GetImage();

    info.Clear();
    info.SetId(iElt2);
    info.SetColumn(1);
    info.SetText(elt1Txt);
    info.SetMask(wxLIST_MASK_TEXT);
    ctrl->SetItem(info);
    info.Clear();
    info.SetId(iElt2);
    info.SetColumn(0);
    info.SetImage(elt1Img);
    info.SetMask(wxLIST_MASK_IMAGE);
    info.SetState(wxLIST_STATE_SELECTED);
    ctrl->SetItem(info);

    info.Clear();
    info.SetId(iElt1);
    info.SetColumn(1);
    info.SetText(elt2Txt);
    info.SetMask(wxLIST_MASK_TEXT);
    ctrl->SetItem(info);
    info.Clear();
    info.SetId(iElt1);
    info.SetColumn(0);
    info.SetImage(elt2Img);
    info.SetMask(wxLIST_MASK_IMAGE);
    ctrl->SetItem(info);
}
