/////////////////////////////////////////////////////////////////////////////
// Name:        browsepanel.h
// Purpose:     wxPackageBrowserPanel definition
// Author:      Julian Smart, Francesco Montorsi
// Modified by:
// Created:     04/06/2006 12:04:43
// RCS-ID:      $Id: browsepanel.h,v 1.4 2007/01/24 23:57:56 frm Exp $
// Copyright:   (c) 2006 Francesco Montorsi
// Licence:     wxWidgets license
/////////////////////////////////////////////////////////////////////////////

#ifndef _PMBROWSEPANEL_H_
#define _PMBROWSEPANEL_H_

/*!
* Includes
*/

#include "wx/notebook.h"
#include "wx/listbox.h"
#include "wx/htmllbox.h"
#include "wx/statusbr.h"

#include "guipm/filterpanel.h"
#include "wxp/package.h"


/*!
* Forward declarations
*/

class wxPackageManager;
class wxPackageViewerPanel;
class wxPackageListBox;


/*!
* Control identifiers
*/

#define SYMBOL_WXPACKAGEBROWSERPANEL_STYLE wxRESIZE_BORDER
#define SYMBOL_WXPACKAGEBROWSERPANEL_TITLE _("Package Browser Panel")
#define SYMBOL_WXPACKAGEBROWSERPANEL_IDNAME wxID_ANY
#define SYMBOL_WXPACKAGEBROWSERPANEL_SIZE wxSize(400, 300)
#define SYMBOL_WXPACKAGEBROWSERPANEL_POSITION wxDefaultPosition
#define ID_BROWSER_NOTEBOOK 10019
#define ID_BROWSER_INSTALLED_FILTER 10007
#define ID_BROWSER_INSTALLED_PACKAGELIST 10005
#define ID_BROWSER_INSTALLED_SELECTALL 10012
#define ID_BROWSER_INSTALLED_DESELECTALL 10015
#define ID_BROWSER_INSTALLED_REFRESH 10016

#define ID_BROWSER_DECOMPRESS 10100
#define ID_BROWSER_REBUILD 10017
#define ID_BROWSER_REINSTALL 10011
#define ID_BROWSER_UNINSTALL 10013
#define ID_BROWSER_UPDATECHECK 10023
#define ID_BROWSER_SOURCELIST 10001
#define ID_BROWSER_NEW_FILTER 10004
#define ID_BROWSER_NEW_PACKAGELIST 10004
#define ID_BROWSER_NEW_SELECTALL 10008
#define ID_BROWSER_NEW_DESELECTALL 10009
#define ID_BROWSER_NEW_REFRESH 10021
#define ID_BROWSER_DOWNLOAD 10022
#define ID_BROWSER_BUILD 10010
#define ID_BROWSER_INSTALL 10014


// ----------------------------------------------------------------------------
// wxPackageListBox
// ----------------------------------------------------------------------------

class wxPackageListBox : public wxHtmlListBox
{
public:
    wxPackageListBox(wxWindow* parent, wxWindowID id = wxID_ANY,
                        const wxPoint& pos = wxDefaultPosition,
                        const wxSize& size = wxDefaultSize, long style = 0,
                        const wxString& name = wxT("commandlistbox"));

public:     // public API

    void Append(const wxPackage &item)
        { m_items.Add(item); SetItemCount(m_items.GetCount()); }

    // NB: call RefreshAll() after all calls to SetString !!
    void SetPackage(unsigned int n, const wxPackage &item)
        { m_items[n] = item; }

    unsigned int GetCount() const
        { return m_items.GetCount(); }

    wxPackageArray &GetPackages()
        { return m_items; }

    bool SetSelectedPackage(const wxPackageId &id)
    {
        // NB: even when n is wxNOT_FOUND we must still
        //     call SetSelection(-1) so to remove selection
        int n = m_items.IndexById(id);
        SetSelection(n);
        return n != wxNOT_FOUND;
    }

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

    wxPackage &GetSelectedPackage()
    {
        wxASSERT_MSG(!HasMultipleSelection(), wxT("Use GetSelectedPackages instead"));
        if (GetSelection() == wxNOT_FOUND)
            return wxEmptyPackage;
        return m_items[GetSelection()];
    }

    wxPackageArray GetSelectedPackages() const
    {
        wxASSERT_MSG(HasMultipleSelection(), wxT("Use GetSelectedPackage instead"));

        wxPackageArray ret;
        unsigned long cookie;
        int item = GetFirstSelected(cookie);
        while ( item != wxNOT_FOUND )
        {
            ret.Add(m_items[item]);
            item = GetNextSelected(cookie);
        }

        return ret;
    }

    wxPackage &GetFirstSelectedPackage() const
    {
        wxASSERT(HasMultipleSelection());
        unsigned long dummy;
        int item = GetFirstSelected(dummy);
        if (item == wxNOT_FOUND)
            return wxEmptyPackage;
        return m_items[item];
    }

    wxPackage &GetPackage(size_t n)
        { return m_items[n]; }

    void Clear()
    {
        wxHtmlListBox::Clear();
        m_items.Clear();
    }

    void ShowStatus(bool show = true)
        { m_bShowStatus=show; }

public:     // misc

    //! Appends the packages from the given array which are not filtered
    //! out by the given filter panel.
    void SetPackages(const wxPackageArray &arr, wxPackageFilterPanel *filter);

protected:
    virtual wxString OnGetItem(size_t n) const;

protected:
    wxPackageArray m_items;
    bool m_bShowStatus;

private:
    DECLARE_NO_COPY_CLASS(wxPackageListBox)
};


// ----------------------------------------------------------------------------
// wxPackageBrowserPanel
// ----------------------------------------------------------------------------

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

public:
    /// Constructors
    wxPackageBrowserPanel( );
    wxPackageBrowserPanel( wxWindow* parent,
                        wxWindowID id = SYMBOL_WXPACKAGEBROWSERPANEL_IDNAME,
                        const wxPoint& pos = SYMBOL_WXPACKAGEBROWSERPANEL_POSITION,
                        const wxSize& size = SYMBOL_WXPACKAGEBROWSERPANEL_SIZE,
                        long style = SYMBOL_WXPACKAGEBROWSERPANEL_STYLE );
    ~wxPackageBrowserPanel();

    /// Creation
    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_WXPACKAGEBROWSERPANEL_IDNAME,
                const wxPoint& pos = SYMBOL_WXPACKAGEBROWSERPANEL_POSITION,
                const wxSize& size = SYMBOL_WXPACKAGEBROWSERPANEL_SIZE,
                long style = SYMBOL_WXPACKAGEBROWSERPANEL_STYLE );

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


public:     // event handlers

    void OnButtonClick(wxCommandEvent &ev);
    void OnUpdateUI(wxUpdateUIEvent &ev);
    void OnListBoxSelected(wxCommandEvent &ev);
    void OnFilterPackages(wxCommandEvent &ev);
    void OnNotebookPageChanged(wxCommandEvent &ev);
    void OnSourceListEnter(wxCommandEvent &ev);
    void OnSourceListSelected(wxCommandEvent &ev);
    void OnPageChanged(wxNotebookEvent &ev);
    void OnProgressPanelEnd(wxCommandEvent &ev);
    void OnIdle(wxIdleEvent& WXUNUSED(ev));

public:     // set/change selected page

    void BrowseLocalPackages()
        { m_pNotebook->ChangeSelection(0); }
    void BrowseNewPackages()
        { m_pNotebook->ChangeSelection(1); }

    bool IsBrowsingLocalPackages() const
        { return m_pNotebook->GetSelection() == 0; }
    bool IsBrowsingNewPackages() const
        { return m_pNotebook->GetSelection() == 1; }

public:     // filter

    void FilterLocalPackages();
    void FilterNewPackages();

    void FilterPackageList();

    void ResetFilter()
        { m_pLocalFilter->Reset(); m_pNewFilter->Reset(); }

    //! Runs the filter on the currently selected panel.
    void Filter();

public:     // selection

    void SelectNewPackage(const wxPackageId &);
    void SelectNewPackage(unsigned int n);

    void SelectLocalPackage(const wxPackageId &);
    void SelectLocalPackage(unsigned int n);

    void RefreshPackageList();
    void RefreshLocalPackages();
    void RefreshNewPackages();

public:     // auxiliary getters

    wxPackageViewerPanel *GetAuxiliaryViewerPanel()
        { return m_pViewerPanel; }
    wxStatusBar *GetAuxiliaryStatusBar()
        { return m_pStatusBar; }
    wxMenuBar *GetAuxiliaryMenuBar()
        { return m_pMenuBar; }

public:     // auxiliary setters

    void SetAuxiliaryViewerPanel(wxPackageViewerPanel *p);
    void SetAuxiliaryMenuBar(wxMenuBar *p)
        { m_pMenuBar=p; }
    void SetAuxiliaryStatusBar(wxStatusBar *p)
        { m_pStatusBar=p; }

public:     // load/save

    bool Load(wxConfigBase *, const wxString &path);
    void Save(wxConfigBase *, const wxString &path) const;

public:     // "high-level" operations

    //! Changes current source of "remote package" list
    //! to the given path and returns true if it's a valid path.
    //! Only remote URLs are allowed (i.e. those starting with
    //! http:// or ftp://); local URLs should be added to the
    //! local package repository array (see #SetLocalRepositoryPaths).
    //! The "get new packages" tab inside this panel is infact appropriate
    //! only for remote packages since it only contains a "Download" button!
    bool BrowseTo(const wxString &path);

    //! Loads a single WXZ package using the given filename to access it.
    bool LoadCompressedPackage(const wxString &wxzpath);

    //! Returns TRUE if the package source currently selected is
    //! not a remote resource.
    bool IsPackageSourceLocal() const;

    //! Downloads the given array of packages queuing them in the
    //! "Downloads" tab of the associated auxiliary viewer panel.
    void Download(const wxPackageArray &arr, bool skipdepcheck = false);
    void Download(const wxPackage &pkg, bool skipdepcheck = false)
    {
        wxPackageArray temp;
        temp.Add(pkg);
        Download(temp, skipdepcheck);
    }


public:     // getters

    wxString GetDefaultDownloadPath() const
        { return m_strDefaultDownloadPath; }
    wxString GetDefaultDecompressionPath() const
        { return m_strDefaultDecompressionPath; }
    wxString GetDefaultInstallationPath() const
        { return m_strDefaultInstallationPath; }
/*
    wxArrayString GetLocalRepositoryPaths() const
        { return m_localRepo; }
*/
    wxPackageArray &GetLocalPackages()
        { return m_arrLocal; }
    wxPackageArray &GetNewPackages()
        { return m_arrNew; }

    //! Returns a new array containing copies of the selected packages.
    wxPackageArray GetSelectedPackages() const;

    bool IsAutoLoadLocalPackagesEnabled() const
        { return m_bAutoLoadLocalPackages; }

public:     // setters

    void SetDefaultDownloadPath(const wxString &path)
        { m_strDefaultDownloadPath=path; }
    void SetDefaultDecompressionPath(const wxString &path)
        { m_strDefaultDecompressionPath=path; }
    void SetDefaultInstallationPath(const wxString &path)
        { m_strDefaultInstallationPath=path; }
/*
    void SetLocalRepositoryPaths(const wxArrayString &arr)
        { m_localRepo=arr; }
*/

    void SetAutoLoadLocalPackages(bool load)
        { m_bAutoLoadLocalPackages=load; }

public:     // static stuff

    // NOTE: the following two static vars cannot be replaced with the
    //       DEFAULT_WXL_FILENAME and DEFAULT_WXL_URL defines since they
    //       are something specific to wxPM/wxP/WXP apps while this file
    //       is part of the libguipm library!

    // Name of the file appended to the URLs which terminate with '/' when
    // downloading the WXL repo descriptor:
    static wxString s_strDefaultWxlName;

    // Default URL for the WXL file:
    static wxString s_strDefaultWxlURL;

protected:      // internal utilities

    // use BrowseTo() from other classes !!
    bool SetRepositoryURL(const wxString &url);

    void EnableCmd(long id, bool enable = true);

    void SetStatusText(const wxString &str)
    {
        if (GetAuxiliaryStatusBar())
            GetAuxiliaryStatusBar()->SetStatusText(str);
    }

protected:      // controls

    wxNotebook* m_pNotebook;
    wxComboBox* m_pSourceList;

    //! The list of remote packages. Holds an other wxPackageArray itself.
    wxPackageListBox* m_pNewList;
    wxPackageFilterPanel* m_pNewFilter;

    //! The list of local packages. Holds an other wxPackageArray itself.
    wxPackageListBox* m_pLocalList;
    wxPackageFilterPanel* m_pLocalFilter;

protected:      // paths

    //! the default path where downloaded WXZ are placed
    wxString m_strDefaultDownloadPath;

    //! the default path where WXZ are decompressed
    wxString m_strDefaultDecompressionPath;

    //! the default path where packages are installed
    wxString m_strDefaultInstallationPath;

protected:      // other variables

    //! the list of local packages loaded from local repositories
    //! NB: when a filter is applied
    //!        m_arrLocal != m_pLocalList->GetItems()
    //!     thus we need two different arrays: one in the control
    //!     (the filtered&displayed list) and one with all local
    //!     un-filtered packages (m_arrLocal).
    wxPackageArray m_arrLocal;

    //! the list of new packages loaded from the curently selected source
    //! NB: see the comments about #m_arrLocal for more info.
    wxPackageArray m_arrNew;

    //! should duplicate packages be shown ?
    bool m_bShowDupPackages;

    //! should the idle event handler call RefreshLocalPackages() ?
    bool m_bNeedLocalPackageRefresh;

    //! need to load wx packages at startup?
    bool m_bAutoLoadLocalPackages;

protected:      // auxiliary windows

    //! the auxiliary wxPackageViewerPanel used to display info
    //! about the package selected in this panel (can be NULL)
    wxPackageViewerPanel *m_pViewerPanel;

    // the auxiliary bars
    wxMenuBar *m_pMenuBar;
    wxStatusBar *m_pStatusBar;
};


#endif
    // _PMBROWSEPANEL_H_
