/////////////////////////////////////////////////////////////////////////////
// Name:        proppanel.h
// Purpose:     wxPackagePropertiesPanel definition
// Author:      Francesco Montorsi
// Modified by:
// Created:     28/06/2006 19:22:48
// RCS-ID:      $Id: proppanel.h,v 1.18 2007/01/30 22:05:22 frm Exp $
// Copyright:   (c) 2006 Julian Smart, Francesco Montorsi
// Licence:     wxWidgets license
/////////////////////////////////////////////////////////////////////////////

#ifndef _PMPROPPANEL_H_
#define _PMPROPPANEL_H_


/*!
 * Includes
 */

#include <wx/listbox.h>

#include "guipm/extcmdoptionspanel.h"
#include "guipkg/excludedlg.h"

#include "wxp/packageutils.h"
#include "wxp/packagedep.h"
#include "wxp/packagecmd.h"
#include "wxp/packagewxp.h"

/*!
 * Forward declarations
 */

class wxListBox;
class wxRadioButton;
class wxRadioBox;
class wxTreeCtrl;
class wxTreeItemId;
class wxStaticBitmap;
class wxDatePickerCtrl;
class wxOptionListCtrl;
class wxSpinCtrl;
class wxPackageSourceEditCtrl;
class wxDirPickerCtrl;
class wxFileDirPickerEvent;
class wxExplorerTreeCtrl;
class wxExplorerTreeEvent;
class wxPackageExcludeListBox;
class wxCheckListBox;
class wxSplitterWindow;

/*!
 * Control identifiers
 */

////@begin control identifiers
#define ID_PROP_PACKAGING_PAGE 1151
#define ID_PROP_TAR 1120
#define ID_PROP_ZIP 1117
#define ID_PROP_FILENAME 1157
#define ID_PROP_UPLOAD 1158
#define ID_PROP_PROJECT_DIR 1100
#define ID_PROP_WXP_DIR 1148
#define ID_PROP_RELATIVE_ROOT 1137
#define ID_PROP_INCLUDED_TREE 1121
#define ID_PROP_REFRESH_INCLUDED 1149
#define ID_PROP_EXPAND_INCLUDED 1135
#define ID_PROP_COLLAPSE_INCLUDED 1136
#define ID_PROP_EXCLUDED 1147
#define ID_PROP_NEW_EXCLUDED 1145
#define ID_PROP_DELETE_EXCLUDED 1146
#define ID_PROP_BASICS_PAGE 1150
#define ID_PROP_NAME 1101
#define ID_PROP_VERSION 1105
#define ID_PROP_DESCRIPTION 1107
#define ID_PROP_KEYWORDS 1109
#define ID_PROP_CATEGORY1 1110
#define ID_PROP_CATEGORY2 1165
#define ID_PROP_LICENSING_PAGE 1152
#define ID_PROP_LICENSE 1103
#define ID_PROP_LICENSE_REF 1127
#define ID_PROP_LICENSETYPE 1111
#define ID_PROP_ORGANISATION 1124
#define ID_PROP_ORGANISATION_WEBSITE 1126
#define ID_PROP_COST 1128
#define ID_PROP_COPYRIGHT 1169
#define ID_PROP_CREDITS 1168
#define ID_PROP_AUTHORS 1104
#define ID_PROP_NEW_AUTHOR 1171
#define ID_PROP_DELETE_AUTHOR 1173
#define ID_PROP_MAINTAINERS 1170
#define ID_PROP_NEW_MAINTAINER 1172
#define ID_PROP_DELETE_MAINTAINER 1174
#define ID_PROP_DETAILS_PAGE 1153
#define ID_PROP_STATUS 1106
#define ID_PROP_CREATIONDATE 1166
#define ID_PROP_PROGLANGUAGE 1108
#define ID_PROP_WEBSITE 1113
#define ID_PROP_RSSFEED 1118
#define ID_PROP_NUMSAMPLES 1122
#define ID_PROP_LOGO_REF 1125
#define ID_PROP_DOWNLOADLINKS 1139
#define ID_PROP_NEW_DOWNLOADLINK 1129
#define ID_PROP_DELETE_DOWNLOADLINK 1130
#define ID_PROP_DOCS 1176
#define ID_PROP_NEW_DOC 1131
#define ID_PROP_DELETE_DOC 1175
#define ID_PROP_SCREENSHOTS 1177
#define ID_PROP_NEW_SCREENSHOT 1178
#define ID_PROP_DELETE_SCREENSHOT 1179
#define ID_PROP_DEPENDENCIES_PAGE 1154
#define ID_PROP_SUPPORTEDPORTS 1119
#define ID_PROP_QUICKSET_SUPPORTED_VERSIONS 1159
#define ID_PROP_TESTEDPORTS 1112
#define ID_PROP_QUICKSET_TESTED_VERSIONS 1160
#define ID_PROP_DEPENDENCIES 1116
#define ID_PROP_NEW_DEP 1141
#define ID_PROP_DELETE_DEP 1167
#define ID_PROP_BUILDSYSTEM_PAGE 1155
#define ID_PROP_BUILDSYS_TYPE 1115
#define ID_PROP_BUILDSYS_FORMATS 1134
#define ID_PROP_BUILDSYS_OPTIONS 1140
#define ID_PROP_NEW_OPTION 1142
#define ID_PROP_DELETE_OPTION 1143
#define ID_PROP_ADD_OPTPRESET 1114
#define ID_PROP_STAGE 1123
#define ID_PROP_TARGETS 1132
#define ID_PROP_BUILDSYS_COMMANDS 1102
#define ID_PROP_NEW_COMMAND 1133
#define ID_PROP_DELETE_COMMAND 1138
#define ID_PROP_RESET_COMMANDS 1144
#define ID_PROP_XMLSOURCE_PAGE 1156
#define SYMBOL_WXPACKAGEPROPERTIESPANEL_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX
#define SYMBOL_WXPACKAGEPROPERTIESPANEL_TITLE _("Package Properties Panel")
#define SYMBOL_WXPACKAGEPROPERTIESPANEL_IDNAME wxID_ANY
#define SYMBOL_WXPACKAGEPROPERTIESPANEL_SIZE wxSize(400, 300)
#define SYMBOL_WXPACKAGEPROPERTIESPANEL_POSITION wxDefaultPosition
////@end control identifiers

#define wxPROPPANEL_DOC_WILDCARD    \
    wxT("HTML docs (*.htm,*.html,*.chm)|*.htm;*.html;*.chm|PDF docs (*.pdf)|*.pdf|Other formats (*.rtf,*.doc,*.txt)|*.rtf;*.doc;*.txt|All files (*)|*")

#define wxPROPPANEL_IMAGE_WILDCARD     \
    wxT("Common image formats (*.gif,*.jpg,*.jpeg,*.png,*.bmp)|*.gif;*.jpg;*.png;*.bmp|All files (*)|*")

#define wxPROPPANEL_XMLSOURCE_PAGE_INDEX    6

// size of the bitmaps used for the buttons:
#define ID_PROPPANEL_BITMAP_SIZE        wxSize(17, 17)


// ----------------------------------------------------------------------------
// global ugly helpers
// ----------------------------------------------------------------------------

void wxDeletePackageDependencyFromListctrl(wxListCtrl *lc, int idx);
void wxDeletePackageDataWithRefFromListbox(wxListBox *lc, int idx);
bool IsSelected(wxListCtrl *lc, int i);
int GetSelection(wxListCtrl *lc);


// ----------------------------------------------------------------------------
// wxPackagePropertiesPanel
// ----------------------------------------------------------------------------

class wxPackagePropertiesPanel: public wxPanel
{
    DECLARE_DYNAMIC_CLASS( wxPackagePropertiesPanel )
    DECLARE_EVENT_TABLE()

public:
    /// Constructors
    wxPackagePropertiesPanel( );
    wxPackagePropertiesPanel( wxWindow* parent, 
                              wxWindowID id = SYMBOL_WXPACKAGEPROPERTIESPANEL_IDNAME, 
                              const wxPoint& pos = SYMBOL_WXPACKAGEPROPERTIESPANEL_POSITION, 
                              const wxSize& size = SYMBOL_WXPACKAGEPROPERTIESPANEL_SIZE, 
                              long style = SYMBOL_WXPACKAGEPROPERTIESPANEL_STYLE );

    /// Creation
    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_WXPACKAGEPROPERTIESPANEL_IDNAME, 
                 const wxPoint& pos = SYMBOL_WXPACKAGEPROPERTIESPANEL_POSITION, 
                 const wxSize& size = SYMBOL_WXPACKAGEPROPERTIESPANEL_SIZE, 
                 long style = SYMBOL_WXPACKAGEPROPERTIESPANEL_STYLE );

    ~wxPackagePropertiesPanel();


    /// Creates the controls and sizers
    void CreateControls();

    /// Should we show tooltips?
    static bool ShowToolTips();

    /// Provides the bitmaps for the wxBitmapButtons used
    wxBitmap GetBitmapResource( const wxString& name );


public:         // event handlers

    // general event handlers

    void OnButton(wxCommandEvent &ev);
    void OnListBoxDClick(wxCommandEvent &ev);

    // licensing

    void OnLicensingButton(wxCommandEvent &ev);
    void OnLicensingListBoxDClick(wxCommandEvent &ev);
    void OnLicenseSelected(wxCommandEvent &ev);
    void OnLicensingPageUpdateUI(wxUpdateUIEvent &ev);

    // build system

    void OnBuildSystemButton(wxCommandEvent &ev);
    void OnBuildSystemListBoxDClick(wxCommandEvent &ev);
    void OnBuildSystemType(wxCommandEvent &ev);
    void OnBuildSystemFormatCheck(wxCommandEvent &ev);
    void OnBuildSystemStage(wxCommandEvent &ev);
    void OnOptionDClick(wxCommandEvent &ev);
    void OnCompilerPreset(wxCommandEvent &ev);
    void OnWxPreset(wxCommandEvent &ev);
    void OnBuildSystemPageUpdateUI(wxUpdateUIEvent &ev);

    // packaging

    void OnPackagingButton(wxCommandEvent &ev);
    void OnText(wxCommandEvent &ev);
    void OnProjectRootChange(wxFileDirPickerEvent &ev);
    void OnWXPDirChange(wxFileDirPickerEvent &ev);
    void OnIncludedTreeCheck(wxExplorerTreeEvent &ev);
    void OnPackagingPageUpdateUI(wxUpdateUIEvent &ev);

    // dependencies

    void OnDependenciesButton(wxCommandEvent &ev);
    void OnDependenciesListBoxDClick(wxCommandEvent &ev);
    void OnDepDClick(wxListEvent &ev);
    void OnDependenciesPageUpdateUI(wxUpdateUIEvent &ev);

    // details

    void OnDetailsButton(wxCommandEvent &ev);
    void OnDetailsListBoxDClick(wxCommandEvent &ev);
    void OnDetailsPageUpdateUI(wxUpdateUIEvent &ev);

    // XML source

    void OnPageChanged(wxNotebookEvent &ev);


public:     // public API

    // returns true if user modified the control since the last
    // call to SetModified(false)
    bool IsModified() const
        { return m_bModified; }

    // sets the control as user modified or not
    void SetModified(bool mod)
        { m_bModified=mod; }

    //! Returns true if this panel contains all controls initialized
    //! with correct data so that a call to GetPackageInfo() will return
    //! a valid wxPackageInfo (i.e. its IsOk() function will return true).
    //! NB: this function will eventually warn the user about what's wrong
    //!     using wxLogError()
    bool IsOk() const;

    //! Returns all the info currently stored in the controls of this panel
    //! in wxPackageInfo form.
    wxPackageInfo GetPackageInfo() const;

    //! Returns the project absolute root
    wxString GetProjectAbsoluteRoot() const
        { return m_strRoot; }

    wxULongLong GetUncompressedSize() const
        { return m_szUncompressed; }

    //! Fills all the controls of this panel with the package info stored
    //! in the given XML document (which the caller must ensure will remain
    //! valid until next SetPackageInfo call).
    //! This overload is preferred over the SetPackageInfo(const wxPackageInfo&)
    //! version since this panel is able to display the XML source, which 
    //! in turn contains some more additional info over wxPackageInfo: 
    //! XML comments and XML indentation, for example.
    //!
    //! Both the overloads take a "filename" parameter to be able to set
    //! the project's WXP directory.
    void SetPackageInfo(const wxPackageXMLDescriptor &descriptor,
                        const wxString &filename = wxEmptyString);

    //! Fills all the controls of this panel with the given package info.
    //! When possible, use the other overload.
    void SetPackageInfo(const wxPackageInfo &descriptor,
                        const wxString &filename = wxEmptyString);

    // wxWindow overrides:
    virtual bool TransferDataFromWindow();


protected:         // internal utils

    bool GetDownloadLink(wxString *ret, const wxString &initial = wxEmptyString);
    bool GetAuthorOrMaintainer(bool isauthor, wxString *ret, wxString *rethref,
                               const wxString &initialname = wxEmptyString,
                               const wxString &initialhref = wxEmptyString);
    bool GetSupportedOrTestedVersionRange(bool issupported,
                                          wxString *ret,
                                          const wxString &portname,
                                          const wxString &initial = wxEmptyString);
    bool GetDoc(wxPackageDataWithRef *ret,
                const wxPackageDataWithRef &initial = wxEmptyPackageDataWithRef);
    bool GetScreenshot(wxPackageDataWithRef *ret,
                       const wxPackageDataWithRef &initial = wxEmptyPackageDataWithRef);
    bool GetDep(wxPackageDependency *ret,
                const wxPackageDependency &initial = wxEmptyPackageDependency);
    bool GetBuildSysOption(wxPackageCommandOption *ret,
                           const wxPackageCommandOption &initial = 
                                            wxEmptyPackageCommandOption);
    bool GetBuildSysCommand(wxPackageCommand *ret,
                            wxPackageBuildSystemStage stage,
                            const wxPackageCommand &initial = wxEmptyPackageCommand);

    // shows the wxPackageExcludeDlg to ask which file/dir/pattern should be excluded
    void GetNewExcludedStuff();

    void UpdatePortVersions();
    void UpdateOptions();
    void UpdateCommands();
    void UpdateXML();
    void UpdateRelativeRoot();
    void UpdateUncompressedSize();

    bool IsPresetOption(const wxString &optname, wxString *presetname) const;
    bool IsUserOption(const wxString &optname) const;

    long GetCompilerFormats() const;

    wxPackageBuildSystemType GetSelBuildSystemType() const
        { return wxIdx2PackageBuildSystemType(m_pBuildSystemType->GetSelection()); }

    // called for any user change:
    void OnUserChange();

    void GetBasicsPackageInfo(wxPackageInfo &pkg) const;
    void GetPackagingPackageInfo(wxPackageInfo &pkg) const;
    void GetLicensingPackageInfo(wxPackageInfo &pkg) const;
    void GetDetailsPackageInfo(wxPackageInfo &pkg) const;
    void GetDependenciesPackageInfo(wxPackageInfo &pkg) const;
    void GetBuildSystemPackageInfo(wxPackageInfo &pkg) const;

    void DoSetPackageInfo(const wxPackageInfo &descriptor, 
                          const wxString &filename);
    void DoSetBasicsPackageInfo(const wxPackageInfo &descriptor);
    void DoSetPackagingPackageInfo(const wxPackageInfo &descriptor, 
                                   const wxString &filename);
    void DoSetLicensingPackageInfo(const wxPackageInfo &descriptor);
    void DoSetDetailsPackageInfo(const wxPackageInfo &descriptor);
    void DoSetDependenciesPackageInfo(const wxPackageInfo &descriptor);
    void DoSetBuildSystemPackageInfo(const wxPackageInfo &descriptor);

    bool IsBasicsPageOk() const;
    bool IsPackagingPageOk() const;
    bool IsLicensingPageOk() const;
    bool IsDetailsPageOk() const;
    bool IsDependenciesPageOk() const;
    bool IsBuildSystemPageOk() const;

    void InitBasicsPage();
    void InitPackagingPage();
    void InitLicensingPage();
    void InitDetailsPage();
    void InitDependenciesPage();
    void InitBuildSystemPage();
    void InitXMLSourcePage();

    // helper for the UpdateUI event handlers
    void DisableIfNoSelection(int todisableID, wxControlWithItems *p)
    {
        FindWindowById(todisableID)->Enable(p->GetSelection() != wxNOT_FOUND);
    }

    // packaging helpers:

    wxString GetProjectParent() const;
    void SetIncludePath(const wxString &path);

    // dependencies helpers:

    void SetPortVersion(int id);

protected:      // controls
    ////@begin wxPackagePropertiesPanel member variables
    wxStaticText* m_pUncompressedSize;
    wxRadioButton* m_pTar;
    wxRadioButton* m_pZip;
    wxTextCtrl* m_pFileName;
    wxTextCtrl* m_pUpload;
    wxDirPickerCtrl* m_pProjectDir;
    wxDirPickerCtrl* m_pWXPDir;
    wxTextCtrl* m_pRelativeRoot;
    wxStaticBitmap* m_pRootBitmap;
    wxStaticText* m_pRootCheckLabel;
    wxExplorerTreeCtrl* m_pIncludedTree;
    wxPackageExcludeListBox* m_pExcluded;
    wxTextCtrl* m_pName;
    wxTextCtrl* m_pVersion;
    wxTextCtrl* m_pDescription;
    wxTextCtrl* m_pKeywords;
    wxChoice* m_pPrimaryCat;
    wxChoice* m_pSecondaryCat;
    wxComboBox* m_pLicense;
    wxChoice* m_pLicenseType;
    wxTextCtrl* m_pOrganization;
    wxTextCtrl* m_pOrganizationWebsite;
    wxTextCtrl* m_pCost;
    wxTextCtrl* m_pCopyright;
    wxTextCtrl* m_pCredits;
    wxListBox* m_pAuthors;
    wxListBox* m_pMaintainers;
    wxChoice* m_pStatus;
    wxDatePickerCtrl* m_pCreationDate;
    wxChoice* m_pProgLang;
    wxTextCtrl* m_pWebsite;
    wxTextCtrl* m_pRSS;
    wxSpinCtrl* m_pNumSamples;
    wxListBox* m_pDownloadLinks;
    wxListBox* m_pDocs;
    wxListBox* m_pScreenshots;
    wxSplitterWindow* m_pSplitter;
    wxPanel* m_pTopPanel;
    wxCheckListBox* m_pSupportedPorts;
    wxCheckListBox* m_pTestedPorts;
    wxPanel* m_pBottomPanel;
    wxListCtrl* m_pDepList;
    wxChoice* m_pBuildSystemType;
    wxCheckListBox* m_pFormats;
    wxStaticText* m_pOptionPresets;
    wxOptionListCtrl* m_pBuildSysOptions;
    wxChoice* m_pBuildSystemStage;
    wxTextCtrl* m_pTargets;
    wxStaticText* m_pCommandPresets;
    wxCommandListBox* m_pBuildSysCommands;
    wxPanel* m_pXMLPanel;
    wxBoxSizer* m_pXMLSizer;
    ////@end wxPackagePropertiesPanel member variables

    wxPackageSourceEditCtrl *m_pEditor;

protected:      // FIXME package data which cannot be edited by the user

    wxString m_strBuildSystemHref;

protected:      // user-inserted data which cannot be stored inside controls

    // the XML source (with user comments & indentation)
    wxPackageXMLDescriptor m_xmlDescriptor;

    // the last valid folder given in the wxDirPickerCtrl in ABSOLUTE form
    // NOTE: this is not always the same of m_pProjectDir->GetPath(): the user
    //       may have modified the path using the text ctrl and thus the path
    //       return by m_pProjectDir->GetPath() may be invalid!
    wxString m_strRoot;

    // misc
    wxPackageDataWithRef m_license, m_logo;

    // stage-dependent

    wxPackageCommandArray m_commands[wxPBST_MAX];
    wxString m_targets[wxPBST_MAX];

protected:      // GUI state helpers (do not hold package data)

    wxPackageCompilerFormat m_formats[wxPCF_MAX];
    wxVersionRange m_supportedVer[wxPORT_MAX];
    wxVersionRange m_testedVer[wxPORT_MAX];
    int m_nLastStage;

    // uncompressed size of selected files
    wxULongLong m_szUncompressed;

    bool m_bRelativeRootValid;

    // was any of the package info modified since last save?
    bool m_bModified;
};


// ----------------------------------------------------------------------------
// wxPackagePropertiesPanel's own events
// ----------------------------------------------------------------------------

BEGIN_DECLARE_EVENT_TYPES()
    DECLARE_EVENT_TYPE(wxEVT_COMMAND_PROPPANEL_USER_CHANGE, 56689)
END_DECLARE_EVENT_TYPES()

#define EVT_PROPPANEL_USER_CHANGE(id, fn) \
    wx__DECLARE_EVT1(wxEVT_COMMAND_PROPPANEL_USER_CHANGE, id, wxCommandEventHandler(fn))


// ----------------------------------------------------------------------------
// wxPackageExcludeListBox - the listbox used by the "packaging" page
// ----------------------------------------------------------------------------

#define wxPELB_DEFAULT_STYLE            (wxLB_SINGLE|wxLB_SORT)

// note that with inherit in protected mode so that the user
// cannot mess directly with the elements of the listbox
class wxPackageExcludeListBox: public wxListBox
{
    DECLARE_DYNAMIC_CLASS( wxPackageExcludeListBox )

public:
    wxPackageExcludeListBox( ) {}
    wxPackageExcludeListBox( wxWindow* parent, 
                             wxWindowID id = wxID_ANY, 
                             const wxPoint& pos = wxDefaultPosition, 
                             const wxSize& size = wxDefaultSize, 
                             long style = wxPELB_DEFAULT_STYLE)
    {
        Create(parent, id, pos, size, style);
    }

    bool Create( wxWindow* parent, wxWindowID id = wxID_ANY, 
                 const wxPoint& pos = wxDefaultPosition, 
                 const wxSize& size = wxDefaultSize, 
                 long style = wxPELB_DEFAULT_STYLE );

    ~wxPackageExcludeListBox() {}

public:     // public API

    void Add(wxPackageExcludeMode type, const wxString &toadd);

    void Add(wxPackageExcludeMode type, const wxArrayString &toadd)
    {
        for (size_t i=0; i<toadd.GetCount(); i++)
            Add(type, toadd[i]);
    }

    wxArrayString Get(wxPackageExcludeMode type) const;
    wxString GetSelection(wxPackageExcludeMode *type) const;

    void Delete(wxPackageExcludeMode type, const wxString &str);
    void DeleteSelected();

    void Clear()
    {
        wxListBox::Clear();
    }

    bool IsEmpty() const
    {
        return wxListBox::GetCount() == 0;
    }

    // VERY IMPORTANT:
    // _any_ time you add/remove, check/uncheck items to the included tree
    // or to the excluded list, you _must_ call one of the following function
    // to ensure that the app remains in a coherent internal state:

    void SynchFromTree(const wxExplorerTreeCtrl *tree);
    void SynchTree(wxExplorerTreeCtrl *tree) const;

protected:      // internal utils

    static wxPackageExcludeMode GetType(const wxString &str);
    static wxString GetContent(const wxString &str);

    bool DoSynchTree(const wxTreeItemId &item,
                    wxExplorerTreeCtrl *tree,
                    const wxString &prefix,
                    const wxArrayString &files,
                    const wxArrayString &dirs,
                    const wxArrayString &patterns) const;
};

#endif
    // _PMPROPPANEL_H_
