/////////////////////////////////////////////////////////////////////////////
// Name:        proppanel_details.cpp
// Purpose:     wxPackagePropertiesPanel
//              (stuff for handling the "details" page)
// Author:      Francesco Montorsi
// Modified by:
// Created:     28/06/2006 19:22:47
// RCS-ID:      $Id: proppanel_details.cpp,v 1.6 2007/01/01 21:36:45 frm Exp $
// Copyright:   (c) 2006 Julian Smart, Francesco Montorsi
// Licence:     wxWidgets license
/////////////////////////////////////////////////////////////////////////////


// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

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

#include <wx/datectrl.h>
#include <wx/spinctrl.h>
#include <wx/filepicker.h>

#include "guipkg/proppanel.h"
#include "guipkg/refeditdlg.h"
#include "guipkg/depeditdlg.h"

#include "wxp/package.h"
#include "wxp/wxp.h"
#include "wxp/packagewxp.h"

#include "wx/miscutils.h"



// ----------------------------------------------------------------------------
// Global helpers
// ----------------------------------------------------------------------------


// some globals wxPackageDataWithRef helpers

wxPackageDataWithRef &wxGetPackageDataWithRefFromListbox(wxListBox *lb, unsigned int idx)
{ return *((wxPackageDataWithRef *)lb->GetClientData(idx)); }

void wxUpdatePackageDataWithRefInListbox(wxListBox *lb, unsigned int idx,
                                         const wxPackageDataWithRef &ref)
{ wxGetPackageDataWithRefFromListbox(lb, idx) = ref; }

wxString wxGetLabelFor(const wxPackageDataWithRef &ref)
{
    // ignore data as actually we prefer to show links to in proppanel
//    if (!ref.GetData().IsEmpty())
//        return ref.GetData();
    if (!ref.GetHref().IsEmpty())
        return ref.GetHref();
    return ref.GetLocalRef();
}

void wxDeletePackageDataWithRefFromListbox(wxListBox *lc, int idx)
{
    if (idx == -1)
    {
        while (lc->GetCount() > 0)
            wxDeletePackageDataWithRefFromListbox(lc, 0);
    }
    else
    {
        // don't leak memory!
        delete ((wxPackageDataWithRef*)lc->GetClientData(idx));
        lc->Delete(idx);
    }
}



// ----------------------------------------------------------------------------
// wxPackagePropertiesPanel - details stuff - I/O
// ----------------------------------------------------------------------------

void wxPackagePropertiesPanel::InitDetailsPage()
{
    m_pStatus->Append(wxArrayString(wxPDS_MAX, wxPackageDevelopmentStatusName));
    m_pProgLang->Append(wxArrayString(wxPPL_MAX, wxPackageProgLanguageName));
    m_pStatus->Select(0);
    m_pProgLang->Select(0);
}

void wxPackagePropertiesPanel::GetDetailsPackageInfo(wxPackageInfo &ret) const
{
    // DETAILS info
    ret.SetDevelopmentStatus((wxPackageDevelopmentStatus)m_pStatus->GetSelection());
    ret.SetProgLanguage((wxPackageProgLanguage)m_pProgLang->GetSelection());
    ret.SetCreationDate(m_pCreationDate->GetValue().Format(wxT("%d %b %Y")));
    ret.SetWebsite(m_pWebsite->GetValue());
    ret.SetRSSHref(m_pRSS->GetValue());

    for (size_t i=0; i<m_pDownloadLinks->GetCount(); i++)
        ret.AddMirror(m_pDownloadLinks->GetString(i));
    for (size_t i=0; i<m_pDocs->GetCount(); i++)
        ret.AddDoc(wxGetPackageDataWithRefFromListbox(m_pDocs, i));
    for (size_t i=0; i<m_pScreenshots->GetCount(); i++)
        ret.AddScreenshot(wxGetPackageDataWithRefFromListbox(m_pScreenshots, i));

    ret.SetLogoRef(m_logo);
    ret.SetNumberOfSamples(m_pNumSamples->GetValue());
}

void wxPackagePropertiesPanel::DoSetDetailsPackageInfo(const wxPackageInfo &p)
{
    // DETAILS info
    m_pStatus->SetSelection(p.GetDevelopmentStatus());
    m_pProgLang->SetSelection(p.GetProgLanguage());

    if (p.GetCreationDate().IsValid())
        m_pCreationDate->SetValue(p.GetCreationDate());
    else
        m_pCreationDate->SetValue(wxDateTime::Now());
    m_pWebsite->SetValue(p.GetWebsite());
    m_pRSS->SetValue(p.GetRSSHref());
    m_logo = p.GetLogoRef();
    m_pNumSamples->SetValue(p.GetNumberOfSamples());

    m_pDownloadLinks->Clear();
    for (size_t i=0; i<p.GetDownloadHref().GetCount(); i++)
        m_pDownloadLinks->Append(p.GetDownloadHref(i));

    // delete all existing wxPackageDataWithRef objects before adding the new ones
    wxDeletePackageDataWithRefFromListbox(m_pDocs, -1); 
    for (size_t i=0; i<p.GetDocumentation().GetCount(); i++)
        m_pDocs->Append(wxGetLabelFor(p.GetDocumentation(i)),
                        (void*)new wxPackageDataWithRef(p.GetDocumentation(i)));

    // delete all existing wxPackageDataWithRef objects before adding the new ones
    wxDeletePackageDataWithRefFromListbox(m_pScreenshots, -1);
    for (size_t i=0; i<p.GetScreenshots().GetCount(); i++)
        m_pScreenshots->Append(wxGetLabelFor(p.GetScreenshot(i)),
                               (void *)new wxPackageDataWithRef(p.GetScreenshot(i)));
}

bool wxPackagePropertiesPanel::IsDetailsPageOk() const
{
    bool isok = true;

    if (m_pDownloadLinks->GetCount() == 0)
    {
        wxLogWarning(wxT("Please provide at least one download link for this package"));
        isok = false;
    }

    return isok;
}



// ----------------------------------------------------------------------------
// wxPackagePropertiesPanel - details stuff
// ----------------------------------------------------------------------------

bool wxPackagePropertiesPanel::GetDownloadLink(wxString *ret, const wxString &def)
{
    wxString newentry(def);

    do
    {
        newentry = wxGetTextFromUser(
                wxT("Please type the URL of a *direct* download link for\nthis package (e.g. http://myproj.sourceforge.net/wxz/thispackage.wxz)..."),
        wxT("Input text"),
        newentry,
        this);
        if (newentry.IsEmpty())
            return false;     // user hit cancel

                    // is this a valid URL ?
        wxURL u(newentry);
        if (u.GetError() != wxURL_NOERR)
            wxLogError(wxT("The URL you entered '%s' does not seems to be a valid URL.\nPlease check its syntax."), newentry.c_str());
        else
            break;      // valid input
    } while (1);

    if (ret) *ret = newentry;
    return true;
}

bool wxPackagePropertiesPanel::GetDoc(wxPackageDataWithRef *ret,
                                      const wxPackageDataWithRef &initial)
{
    wxPackageReferenceEditDlg dlg(this);

    // force the user to choose a path which is "under" the project directory path
    //dlg.SetLocalRoot(m_strRoot);
    dlg.SetLocalRoot(m_pProjectDir->GetPath());
    dlg.SetWildcard(wxPROPPANEL_DOC_WILDCARD);

    dlg.SetRef(initial);
    if (dlg.ShowModal() == wxID_OK)
    {
        wxString type = wxT("unknown");

#if 0       // to enable as soon as wxTheMimeTypesManager works correctly
        wxString ext = dlg.GetRef().GetHref().AfterLast(wxT('.'));
        if (!ext.IsEmpty())
        {
            wxFileType *ft = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
            if (ft)
            {
                if (!ft->GetMimeType(&type))
                    type = wxT("unknown");
            }
        }
#endif

        wxPackageDataWithRef ref(dlg.GetRef());
        ref.SetData(type);
        if (ret) *ret = ref;

        return true;
    }

    return false;
}

bool wxPackagePropertiesPanel::GetScreenshot(wxPackageDataWithRef *ret,
                                             const wxPackageDataWithRef &initial)
{
    wxPackageReferenceEditDlg dlg(this);

    // force the user to choose a path which is "under" the project directory path
    dlg.SetLocalRoot(m_strRoot);
    dlg.SetWildcard(wxPROPPANEL_IMAGE_WILDCARD);

    dlg.SetRef(initial);
    if (dlg.ShowModal() == wxID_OK)
    {
        if (ret) *ret = dlg.GetRef();
        return true;
    }

    return false;
}


// ----------------------------------------------------------------------------
// wxPackagePropertiesPanel - event handlers
// ----------------------------------------------------------------------------

void wxPackagePropertiesPanel::OnDetailsButton(wxCommandEvent &ev)
{
    OnUserChange();

    switch (ev.GetId())
    {
    case ID_PROP_NEW_DOWNLOADLINK:
        {
            wxString newentry;
            if (GetDownloadLink(&newentry))
                m_pDownloadLinks->Append(newentry);
        }
        break;

    case ID_PROP_NEW_DOC:
        {
            wxPackageDataWithRef ref;
            if (GetDoc(&ref, ref))
                m_pDocs->Append(wxGetLabelFor(ref),
                                (void *)new wxPackageDataWithRef(ref));
        }
        break;

    case ID_PROP_NEW_SCREENSHOT:
        {
            wxPackageDataWithRef ref;
            if (GetScreenshot(&ref))
                m_pScreenshots->Append(wxGetLabelFor(ref),
                                       (void *)new wxPackageDataWithRef(ref));
        }
        break;

    case ID_PROP_LOGO_REF:
        {
            wxPackageReferenceEditDlg dlg(this);

            // force the user to choose a path which is "under" the project directory path
            dlg.SetLocalRoot(m_strRoot);
            dlg.SetWildcard(wxPROPPANEL_IMAGE_WILDCARD);

            dlg.SetRef(m_logo);
            if (dlg.ShowModal() == wxID_OK)
                m_logo = dlg.GetRef();
        }
        break;

    case ID_PROP_DELETE_DOWNLOADLINK:
        {
            wxListBox *p = NULL;
            switch (ev.GetId())
            {
                case ID_PROP_DELETE_AUTHOR: p=m_pAuthors; break;
                case ID_PROP_DELETE_MAINTAINER: p=m_pMaintainers; break;
                case ID_PROP_DELETE_DOWNLOADLINK: p=m_pDownloadLinks; break;
                default: wxASSERT(0);
            }
            wxASSERT(p->GetSelection() != wxNOT_FOUND);
            p->Delete(p->GetSelection());
        }
        break;

        // listboxes with untyped data which we have to delete ourselves
    case ID_PROP_DELETE_DOC:
    case ID_PROP_DELETE_SCREENSHOT:
        {
            wxListBox *p = NULL;
            switch (ev.GetId())
            {
                case ID_PROP_DELETE_DOC:
                    p=m_pDocs;
                    break;
                case ID_PROP_DELETE_SCREENSHOT:
                    p=m_pScreenshots;
                    break;

                default: wxASSERT(0);
            }
            wxASSERT(p->GetSelection() != wxNOT_FOUND);
            wxDeletePackageDataWithRefFromListbox(p, p->GetSelection());
        }
        break;
    }
}

void wxPackagePropertiesPanel::OnDetailsListBoxDClick(wxCommandEvent &ev)
{
    OnUserChange();

    switch (ev.GetId())
    {
        case ID_PROP_DOWNLOADLINKS:
        {
            int idx = m_pDownloadLinks->GetSelection();
            if (idx == wxNOT_FOUND)
            {
                // this may happen on wxMSW 's listboxes when they have > 0 items
                // and the user clicks on the empty space
                return;
            }

            wxString newentry;
            if (GetDownloadLink(&newentry, m_pDownloadLinks->GetString(idx)))
                m_pDownloadLinks->SetString(idx, newentry);
        }
        break;

        case ID_PROP_DOCS:
        {
            int idx = m_pDocs->GetSelection();
            if (idx == wxNOT_FOUND)
            {
                // this may happen on wxMSW 's listboxes when they have > 0 items
                // and the user clicks on the empty space
                return;
            }

            wxPackageDataWithRef newentry;
            if (GetDoc(&newentry, wxGetPackageDataWithRefFromListbox(m_pDocs, idx)))
            {
                m_pDocs->SetString(idx, wxGetLabelFor(newentry));
                wxUpdatePackageDataWithRefInListbox(m_pDocs, idx, newentry);
            }
        }
        break;

        case ID_PROP_SCREENSHOTS:
        {
            int idx = m_pScreenshots->GetSelection();
            if (idx == wxNOT_FOUND)
            {
                // this may happen on wxMSW 's listboxes when they have > 0 items
                // and the user clicks on the empty space
                return;
            }

            wxPackageDataWithRef newentry;
            if (GetScreenshot(&newentry,
                              wxGetPackageDataWithRefFromListbox(m_pScreenshots, idx)))
            {
                m_pScreenshots->SetString(idx, wxGetLabelFor(newentry));
                wxUpdatePackageDataWithRefInListbox(m_pScreenshots, idx, newentry);
            }
        }
        break;
    }
}

void wxPackagePropertiesPanel::OnDetailsPageUpdateUI(wxUpdateUIEvent &WXUNUSED(ev))
{
    DisableIfNoSelection(ID_PROP_DELETE_DOWNLOADLINK, m_pDownloadLinks);
    DisableIfNoSelection(ID_PROP_DELETE_DOC, m_pDocs);
    DisableIfNoSelection(ID_PROP_DELETE_SCREENSHOT, m_pScreenshots);
}
