/***************************************************************************
 *   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 "imageviewer_pelt.h"

#include <math.h>

#include <wx/image.h>
#include <wx/window.h>
#include <wx/stattext.h>

#include "bmp_id.h"
#include "components/stdgui/timageviewer.h"
#include "components/stdgui/tbitmap.h"
#include "components/stdgui/tpanel.h"
#include "components/stdgui/tgenbutton.h"
#include "components/framework/tapplication.h"
#include "components/framework/tapplicationpanel.h"
#include "components/framework/tapplwindow.h"
#include "lib/lib_file.h"
#include "lib/lib_logging.h"

ImageViewerPanelElement::ImageViewerPanelElement(TApplicationPanel * _owner, int iID)
    : FileViewerPanelElement(_owner, iID),
        imageViewer(NULL),
        bmp(NULL),
        btnZoomIn(NULL),
        btnZoomOut(NULL),
        btnAdjustZoom(NULL),
        lblZoom(NULL),
        btnOpenExternaly(NULL),
        bUpdatingZoom(false)
{
    wxInitAllImageHandlers();
    this->setName(wxTr("Image"));
    this->setBitmaps(GET_BMP(BMP_FILE_IMAGE_ID),GET_BMP(BMP_FILE_IMAGE_ID));
}

ImageViewerPanelElement::~ImageViewerPanelElement()
{
    this->imageViewer = NULL;

    if(this->bmp)
        delete this->bmp;
    this->bmp = NULL;
}

/** construit le panneau conteneur et son contenu (appellé automatiquement par getContentPanel et détruit automatiquement par le destructeur) */
TPanel * ImageViewerPanelElement::buildContentPanel()
{
    TPanel * contentPanel = new TPanel(dynamic_cast<wxWindow *>(this->getOwner()->getOwner()));
    wxBoxSizer * sizer = new wxBoxSizer( wxVERTICAL);
    contentPanel->SetSizer(sizer);

    TPanel * buttonsPanel = new TPanel(contentPanel);
    wxBoxSizer * btnSizer = new wxBoxSizer( wxHORIZONTAL);
    buttonsPanel->SetSizer(btnSizer);

    this->btnZoomIn = new TGenButton(buttonsPanel);
    this->btnZoomIn->setBitmap(GET_BMP(BMP_MAGNIFIER_PLUS_ID));
    this->btnZoomIn->SetToolTip(wxTr("Zoom in"));
    this->btnZoomIn->addButtonListener(this);
    btnSizer->Add(this->btnZoomIn,0,wxEXPAND);

    this->btnZoomOut = new TGenButton(buttonsPanel);
    this->btnZoomOut->setBitmap(GET_BMP(BMP_MAGNIFIER_MINUS_ID));
    this->btnZoomOut->SetToolTip(wxTr("Zoom out"));
    this->btnZoomOut->addButtonListener(this);
    btnSizer->Add(this->btnZoomOut,0,wxEXPAND);

    this->btnAdjustZoom = new TGenButton(buttonsPanel);
    this->btnAdjustZoom->setBitmap(GET_BMP(BMP_MAGNIFIER_FIT_ID));
    this->btnAdjustZoom->setToggleable(true);
    this->btnAdjustZoom->SetToolTip(wxTr("Adjust zoom"));
    this->btnAdjustZoom->addButtonListener(this);
    btnSizer->Add(this->btnAdjustZoom,0,wxEXPAND);

    this->lblZoom = new wxStaticText(buttonsPanel, -1, wxTr("Zoom level"));
    btnSizer->Add(this->lblZoom,0,wxEXPAND);

    btnSizer->AddStretchSpacer(1);

    this->btnOpenExternaly = new TGenButton(buttonsPanel);
    this->btnOpenExternaly->setBitmap(GET_BMP(BMP_FILE_IMAGE_ID));
    this->btnOpenExternaly->SetToolTip(wxTr("Open externaly"));
    this->btnOpenExternaly->addButtonListener(this);
    btnSizer->Add(this->btnOpenExternaly,0,wxEXPAND);


    sizer->Add(buttonsPanel,0,wxEXPAND);
    sizer->Show(buttonsPanel,true);

    this->imageViewer = new TImageViewer(contentPanel);
    sizer->Add(this->imageViewer,1,wxEXPAND);
    sizer->Show(this->imageViewer,true);

    this->imageViewer->setZoom(0.0);

    this->updateZoomInfos();

    return contentPanel;
}

/** charge un fichier apres avoir vidangé le contenu du composant */
bool ImageViewerPanelElement::loadFileImpl(const wxString & sFile)
{
    this->imageViewer->setBitmap(NULL);

    if(this->bmp)
        delete this->bmp;
    this->bmp = NULL;

    this->bmp = new TBitmap(sFile,wxBITMAP_TYPE_ANY);

    if(!this->bmp->Ok())
    {
        delete this->bmp;
        this->bmp = NULL;
        return false;
    }

    this->imageViewer->setBitmap(this->bmp);
    return true;
}

/** ecris un fichier */
bool ImageViewerPanelElement::writeFileImpl(const wxString & sFile)
{
    return false;
}

/** un bouton a ete active */
void ImageViewerPanelElement::buttonActivated(TGenButton * btn)
{
    if(btn == this->btnZoomIn)
    {
        if(this->imageViewer->getZoom() <= 0.0)
            this->imageViewer->setZoom(1.0);
        else
            this->imageViewer->setZoom(this->imageViewer->getZoom()*5.0/4.0);

        this->updateZoomInfos();
    }
    else if(btn == this->btnZoomOut)
    {
        if(this->imageViewer->getZoom() <= 0.0)
            this->imageViewer->setZoom(1.0);
        else
            this->imageViewer->setZoom(this->imageViewer->getZoom()*4.0/5.0);

        this->updateZoomInfos();
    }
    else if(btn == this->btnOpenExternaly)
    {
        wxString sExt = libfile::extension(this->getFilename()).MakeLower();
        wxFileType * ft = CurrentApplication()->getMimeTypesManager().GetFileTypeFromExtension(sExt);
        if(ft)
        {
            wxString sMimeType;
            ft->GetMimeType(&sMimeType);
            bool bSucceed = false;
            wxString sCmd = ft->GetOpenCommand(this->getFilename());
            if(sCmd.length())
            {
                wxExecute(sCmd, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER);
                bSucceed = true;
            }
            else
            {
                ft = CurrentApplication()->getMimeTypesManager().GetFileTypeFromMimeType(sMimeType);
                sCmd = ft->GetOpenCommand(this->getFilename());
                if(sCmd.length())
                {
                    wxExecute(sCmd, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER);
                    bSucceed = true;
                }
            }
            
            if(!bSucceed)
                wxMessageBox(wxString::Format(wxTr("No application found to open %s files"),sMimeType.c_str()),wxTr("Error"),wxOK|wxICON_EXCLAMATION);
        }
        else
        {
            wxMessageBox(wxString::Format(wxTr("Unknown file type. Unable to open %s"),this->getFilename().c_str()),wxTr("Error"),wxOK|wxICON_EXCLAMATION);
        }
    }
}

/** un bouton a ete bascule */
void ImageViewerPanelElement::buttonToggled(TGenButton * btn)
{
    if(btn == this->btnAdjustZoom)
    {
        if(this->bUpdatingZoom)
            return;

        if(this->btnAdjustZoom->isToggled())
            this->imageViewer->setZoom(0.0);
        else
            this->imageViewer->setZoom(1.0);

        this->updateZoomInfos();
    }
}

/** mets a jour les infos de zoom */
void ImageViewerPanelElement::updateZoomInfos()
{
    this->bUpdatingZoom = true;
    this->btnAdjustZoom->setToggled(this->imageViewer->getZoom() <= 0.0);

    if(this->btnAdjustZoom->isToggled())
        this->lblZoom->SetLabel(wxTr("Zoom : auto"));
    else
    {
        int iZoomPercentage = int(roundf(this->imageViewer->getZoom()*100.0));
        this->lblZoom->SetLabel(wxString::Format(wxTr("Zoom : %d %%"),iZoomPercentage));
    }

    this->bUpdatingZoom = false;
}
