///////////////////////////////////////////////////////////////////////////////
// Name:        smartmsgdlg.cpp
// Purpose:     wxSmartMessageDialog
// Author:      Francesco Montorsi
// Modified by:
// Created:     10/7/2006
// RCS-ID:      $Id: smartmsgdlg.cpp,v 1.1.1.1 2006/12/12 09:39:39 frm Exp $
// Copyright:   (c) Francesco Montorsi
// Licence:     wxWindows licence
///////////////////////////////////////////////////////////////////////////////

// ============================================================================
// declarations
// ============================================================================

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/checkbox.h"
    #include "wx/wx.h"
#endif

#include "guipm/smartmsgdlg.h"
#include "wx/artprov.h"
#include "wx/statline.h"
#include "wx/module.h"

// statics
wxConfigBase *wxSmartMessageDialog::m_pCfg = NULL;
wxString wxSmartMessageDialog::m_strPath = wxT("/Messages");

wxStringHashMap wxSmartMessageDialog::s_hashDesc;



// ============================================================================
// implementation
// ============================================================================

// ----------------------------------------------------------------------------
// wxSmartMessageDialog
// ----------------------------------------------------------------------------

BEGIN_EVENT_TABLE(wxSmartMessageDialog, wxDialog)
        EVT_BUTTON(wxID_YES, wxSmartMessageDialog::OnYes)
        EVT_BUTTON(wxID_NO, wxSmartMessageDialog::OnNo)
        EVT_BUTTON(wxID_CANCEL, wxSmartMessageDialog::OnCancel)
END_EVENT_TABLE()

IMPLEMENT_CLASS(wxSmartMessageDialog, wxDialog)

wxSmartMessageDialog::wxSmartMessageDialog(const wxString &keyname)
{
    m_bShowAgain=true;
    m_pDoNotShowAgain=NULL;
    m_strKeyName=keyname;

    wxASSERT_MSG(s_hashDesc.count(keyname) == 1,
                 wxT("This message is not registered in wxSmartMessageDialogModule!!"));
    Load();
}

bool wxSmartMessageDialog::Create( wxWindow *parent,
                                    const wxString& message,
                                    const wxString& caption,
                                    long style,
                                    const wxPoint& pos)
{
    if (!wxDialog::Create( parent, wxID_ANY, caption, pos, wxDefaultSize, wxDEFAULT_DIALOG_STYLE ))
        return false;

    SetMessageDialogStyle(style);

    bool is_pda = (wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA);

    wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );

    wxBoxSizer *icon_text = new wxBoxSizer( wxHORIZONTAL );

#if wxUSE_STATBMP
    // 1) icon
    if (style & wxICON_MASK)
    {
        wxBitmap bitmap;
        switch ( style & wxICON_MASK )
        {
            default:
                wxFAIL_MSG(_T("incorrect log style"));
                // fall through

            case wxICON_ERROR:
                bitmap = wxArtProvider::GetIcon(wxART_ERROR, wxART_MESSAGE_BOX);
                break;

            case wxICON_INFORMATION:
                bitmap = wxArtProvider::GetIcon(wxART_INFORMATION, wxART_MESSAGE_BOX);
                break;

            case wxICON_WARNING:
                bitmap = wxArtProvider::GetIcon(wxART_WARNING, wxART_MESSAGE_BOX);
                break;

            case wxICON_QUESTION:
                bitmap = wxArtProvider::GetIcon(wxART_QUESTION, wxART_MESSAGE_BOX);
                break;
        }
        wxStaticBitmap *icon = new wxStaticBitmap(this, wxID_ANY, bitmap);
        if (is_pda)
            topsizer->Add( icon, 0, wxTOP|wxLEFT|wxRIGHT | wxALIGN_LEFT, 10 );
        else
            icon_text->Add( icon, 0, wxCENTER );
    }
#endif // wxUSE_STATBMP

#if wxUSE_STATTEXT
    // 2) text
    icon_text->Add( CreateTextSizer( message ), 0, wxALIGN_CENTER | wxLEFT, 10 );

    topsizer->Add( icon_text, 1, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 );
#endif // wxUSE_STATTEXT

    // My modification
    // ===================================================

    topsizer->AddSpacer(10);

    wxString label;
    if (style & wxYES_NO)
        label = _("Do not ask next time - assume 'Yes' as reply.");
    else
        label = _("Do not show this message next time.");

    m_pDoNotShowAgain = new wxCheckBox(this, wxID_ANY, label);
    m_pDoNotShowAgain->SetValue(!m_bShowAgain);
    topsizer->Add(m_pDoNotShowAgain, 0, wxGROW|wxLEFT|wxRIGHT|wxTOP, 10);

    // End of my mod
    // ================


#if wxUSE_STATLINE
    // 3) static line
    topsizer->Add( new wxStaticLine( this, wxID_ANY ), 0, wxEXPAND | wxLEFT|wxRIGHT|wxTOP, 10 );
#endif // wxUSE_STATLINE

    // 4) buttons
    int center_flag = wxEXPAND;
    if (style & wxYES_NO) center_flag = wxALIGN_CENTRE;
    topsizer->Add( CreateButtonSizer( style & (wxOK|wxCANCEL|wxYES_NO|wxYES_DEFAULT|wxNO_DEFAULT) ),
                   0, center_flag | wxALL, 10 );

    SetAutoLayout( true );
    SetSizer( topsizer );

    topsizer->SetSizeHints( this );
    topsizer->Fit( this );
    wxSize size( GetSize() );
    if (size.x < size.y*3/2)
    {
        size.x = size.y*3/2;
        SetSize( size );
    }

    Centre( wxBOTH | wxCENTER_FRAME);

    return true;
}

void wxSmartMessageDialog::OnYes(wxCommandEvent& WXUNUSED(event))
{
    EndModal( wxID_YES );
}

void wxSmartMessageDialog::OnNo(wxCommandEvent& WXUNUSED(event))
{
    EndModal( wxID_NO );
}

void wxSmartMessageDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
{
    // Allow cancellation via ESC/Close button except if
    // only YES and NO are specified.
    const long style = GetMessageDialogStyle();
    if ( (style & wxYES_NO) != wxYES_NO || (style & wxCANCEL) )
    {
        EndModal( wxID_CANCEL );
    }
}



// ----------------------------------------------------------------------------
// wxSmartMessageBox
// ----------------------------------------------------------------------------

int wxSmartMessageBox(const wxString &keyname,
                        const wxString& message,
                        const wxString& caption,
                        long style,
                        wxWindow *parent)
{
    wxSmartMessageDialog dlg(keyname);

    if (dlg.ShowAgain())
    {
        dlg.Create(parent, message, caption, style);
        return dlg.ShowModal();
    }
    else
    {
        // when not showing a smart message box which has the wxYES_NO
        // style, it is always a wxYES to be implied
        if (style & wxYES_NO)
            return wxID_YES;
        return wxID_OK;
    }
}



// ----------------------------------------------------------------------------
// wxSmartLog* family
// ----------------------------------------------------------------------------

#define LOG_BUFFER_SIZE   (4096)
static wxChar s_szSmartBufStatic[LOG_BUFFER_SIZE];

// wrapper for wxVsnprintf(s_szBuf) which always NULL-terminates it
static inline void PrintfInLogBuf(const wxChar *szFormat, va_list argptr)
{
    if ( wxVsnprintf(s_szSmartBufStatic, LOG_BUFFER_SIZE, szFormat, argptr) < 0 )
    {
        // must NUL-terminate it manually
        s_szSmartBufStatic[LOG_BUFFER_SIZE - 1] = _T('\0');
    }
    //else: NUL-terminated by vsnprintf()
}

inline int ShowMessageBox(const wxChar *keyname, const wxChar *msg)
{
    return wxSmartMessageBox(keyname, msg,
                      _("Message"), wxOK|wxICON_INFORMATION);
}

inline int ShowWarningBox(const wxChar *keyname, const wxChar *msg)
{
    return wxSmartMessageBox(keyname, msg,
                      _("Warning"), wxOK|wxICON_WARNING);
}

inline int ShowErrorBox(const wxChar *keyname, const wxChar *msg)
{
    return wxSmartMessageBox(keyname, msg,
                      _("Error"), wxOK|wxICON_ERROR);
}

inline int ShowYesNoQuestionBox(const wxChar *keyname, const wxChar *msg)
{
    return wxSmartMessageBox(keyname, msg,
                      _("Question"), wxYES_NO|wxICON_QUESTION);
}

#define IMPLEMENT_SMARTLOG_FUNCTION(level)                          \
  int wxSmartVLog##level(const wxChar *keyname,                     \
                          const wxChar *szFormat, va_list argptr)   \
  {                                                                 \
    PrintfInLogBuf(szFormat, argptr);                               \
    return Show##level##Box(keyname, s_szSmartBufStatic);           \
  }                                                                 \
                                                                    \
  int wxSmartLog##level(const wxChar *keyname,                      \
                         const wxChar *szFormat, ...)               \
  {                                                                 \
    va_list argptr;                                                 \
    va_start(argptr, szFormat);                                     \
    int ret = wxSmartVLog##level(keyname, szFormat, argptr);        \
    va_end(argptr);                                                 \
    return ret;                                                     \
  }

IMPLEMENT_SMARTLOG_FUNCTION(Message)
IMPLEMENT_SMARTLOG_FUNCTION(Warning)
IMPLEMENT_SMARTLOG_FUNCTION(Error)
IMPLEMENT_SMARTLOG_FUNCTION(YesNoQuestion)



// ----------------------------------------------------------------------------
// wxSmartMessageDialogModule
// ----------------------------------------------------------------------------

class wxSmartMessageDialogModule : public wxModule
{
    DECLARE_DYNAMIC_CLASS(wxSmartMessageDialogModule)

public:
    wxSmartMessageDialogModule() { }

    virtual void OnExit() {}

    virtual bool OnInit()
    {
        wxStringHashMap &h = wxSmartMessageDialog::s_hashDesc;

        h[wxT("updatecheck")] = _("Ask for the download of updated packages");
        h[wxT("depconflict")] = _("Ask for ignoring conflicting dependencies");
        h[wxT("ignoredep")] = _("Ask for ignoring conflicting dependencies");
        h[wxT("nowxbuilds")] = _("Warn about no wxWidgets builds defined");
        h[wxT("deletepresetopt")] = _("Warn when deleting an option which is part of a preset");
        h[wxT("editpresetopt")] = _("Warn when editing an option which is part of a preset");
        h[wxT("changewxbuild")] = _("Warn about options automatically changed when selecting a wxWidgets build");
        h[wxT("internetconn")] = _("Warn about Internet connection down");

        return true;
    }
};

IMPLEMENT_DYNAMIC_CLASS(wxSmartMessageDialogModule, wxModule)
