//////////////////////////////////////////////////////////////////////
// This file was auto-generated by codelite's wxCrafter Plugin
// Do not modify this file by hand!
//////////////////////////////////////////////////////////////////////

#ifndef __OpenResourceDialogModel_GUARD__H__
#define __OpenResourceDialogModel_GUARD__H__

#include <algorithm>
#include <wx/clntdata.h>
#include <wx/dataview.h>
#include <wx/variant.h>

/**
 * @brief each item in the wxDataViewCtrl is represented in the model by this class.
 * m_data - contains the data (columns values) as passed when adding an item to the wxDataViewCtrl model class
 * m_clientData - is the user client data (owned by the model)
 * To convert between a wxDataViewItem to a OpenResourceDialogModel_Item class, simply use:
 * @code
 * OpenResourceDialogModel_Item* itemData = reinterpret_cast<OpenResourceDialogModel_Item*>( item.GetID() );
 * if ( itemData ) {
 *      // you can now traverese the tree or have a direct access to the model internal data
 *      // note that you must not delete itemData as it is owned by the model and
 * }
 * @endcode
 */
class OpenResourceDialogModel_Item
{
protected:
    wxVector<wxVariant> m_data;
    OpenResourceDialogModel_Item* m_parent;
    wxVector<OpenResourceDialogModel_Item*> m_children;
    bool m_isContainer;
    wxClientData* m_clientData;

public:
    OpenResourceDialogModel_Item()
        : m_parent(NULL)
        , m_isContainer(false)
        , m_clientData(NULL)
    {
    }
    virtual ~OpenResourceDialogModel_Item()
    {
        if(m_clientData) {
            delete m_clientData;
            m_clientData = NULL;
        }
        m_data.clear();

        // Delete our children
        // since the deletion of a child may alter its parent m_children array
        // we use a temporary vector for the loop
        wxVector<OpenResourceDialogModel_Item*> tmpChildren = m_children;
        while(!tmpChildren.empty()) {
            delete(*tmpChildren.begin());
            tmpChildren.erase(tmpChildren.begin());
        }
        m_children.clear();

        // Remove us from the parent
        if(m_parent) {
            m_parent->RemoveChild(this);
        }
    }

    void SetIsContainer(bool b) { m_isContainer = b; }

    bool IsContainer() const { return m_isContainer; }

    /**
     * @brief remove a child from this node and free its memory
     * @param child
     */
    void DeleteChild(OpenResourceDialogModel_Item* child)
    {
        wxVector<OpenResourceDialogModel_Item*>::iterator iter = std::find(m_children.begin(), m_children.end(), child);
        if(iter != m_children.end()) {
            delete *iter;
            m_children.erase(iter);
        }
    }

    /**
     * @brief remove child from this node without freeing its memory
     * @param child
     */
    void RemoveChild(OpenResourceDialogModel_Item* child)
    {
        wxVector<OpenResourceDialogModel_Item*>::iterator iter = std::find(m_children.begin(), m_children.end(), child);
        if(iter != m_children.end()) {
            m_children.erase(iter);
        }
    }

    /**
     * @brief add child to this node
     */
    void AddChild(OpenResourceDialogModel_Item* child)
    {
        m_children.push_back(child);
        child->m_parent = this;
    }

    bool IsRoot() const { return m_parent == NULL; }

    // Setters / Getters
    void SetChildren(const wxVector<OpenResourceDialogModel_Item*>& children) { this->m_children = children; }
    void SetData(const wxVector<wxVariant>& data) { this->m_data = data; }
    void SetParent(OpenResourceDialogModel_Item* parent) { this->m_parent = parent; }
    const wxVector<OpenResourceDialogModel_Item*>& GetChildren() const { return m_children; }
    wxVector<OpenResourceDialogModel_Item*>& GetChildren() { return m_children; }
    const wxVector<wxVariant>& GetData() const { return m_data; }
    wxVector<wxVariant>& GetData() { return m_data; }
    OpenResourceDialogModel_Item* GetParent() { return m_parent; }

    void SetClientObject(wxClientData* data)
    {
        if(m_clientData) {
            delete m_clientData;
        }
        m_clientData = data;
    }

    wxClientData* GetClientObject() const { return m_clientData; }
};

//////////////////////////////////////////////
// The TreeListCtrl model
//////////////////////////////////////////////

class OpenResourceDialogModel : public wxDataViewModel
{
protected:
    wxVector<OpenResourceDialogModel_Item*> m_data;
    unsigned int m_colCount;

public:
    OpenResourceDialogModel();
    virtual ~OpenResourceDialogModel();

    /**
     * @brief a helper method creating a wxVariant containing both bitmap and text
     * this is useful when mostly when populating a column of type 'icontext'
     */
    static wxVariant CreateIconTextVariant(const wxString& text, const wxBitmap& bmp);

    void SetColCount(unsigned int colCount) { this->m_colCount = colCount; }
    void SetData(const wxVector<OpenResourceDialogModel_Item*> data) { this->m_data = data; }
    unsigned int GetColCount() const { return m_colCount; }
    const wxVector<OpenResourceDialogModel_Item*>& GetData() const { return m_data; }
    wxVector<OpenResourceDialogModel_Item*>& GetData() { return m_data; }

    virtual bool HasContainerColumns(const wxDataViewItem& item) const { return true; }

public:
    // Make the functions below 'virtual' so the user may override them
    virtual unsigned int GetColumnCount() const;
    virtual wxString GetColumnType(unsigned int col) const;
    virtual void GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const;
    virtual bool SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col);

protected:
    // Helpers
    virtual wxDataViewItem DoAppendItem(const wxDataViewItem& parent, const wxVector<wxVariant>& data, bool isContainer,
                                        wxClientData* clientData = NULL);
    virtual wxDataViewItem DoInsertItem(const wxDataViewItem& insertBeforeMe, const wxVector<wxVariant>& data,
                                        bool isContainer, wxClientData* clientData);
    virtual void DoChangeItemType(const wxDataViewItem& item, bool changeToContainer);

public:
    /**
     * @brief Append a line to the model
     * clientData will be owned by the model once added (i.e. the clientData must be allocated on the heap and it will
     * be freed by the model)
     */
    virtual wxDataViewItem AppendItem(const wxDataViewItem& parent, const wxVector<wxVariant>& data,
                                      wxClientData* clientData = NULL);

    /**
     * @brief Append a lines to the model
     */
    virtual wxDataViewItemArray AppendItems(const wxDataViewItem& parent, const wxVector<wxVector<wxVariant>>& data);

    /**
     * @brief delete an item and all its children
     * @param parent
     */
    virtual void DeleteItem(const wxDataViewItem& item);

    /**
     * @brief delete an item
     * @param parent
     */
    virtual void DeleteItems(const wxDataViewItem& parent, const wxDataViewItemArray& items);

    /**
     * @brief update an item data + client-data
     */
    virtual void UpdateItem(const wxDataViewItem& item, const wxVector<wxVariant>& data);

    /**
     * @brief insert an item into the model before 'insertBeforeMe' item. Return the newly inserted item on success
     */
    virtual wxDataViewItem InsertItem(const wxDataViewItem& insertBeforeMe, const wxVector<wxVariant>& data,
                                      wxClientData* clientData = NULL);

    /**
     * @brief clear the control and delete all its content
     */
    virtual void Clear();

    virtual bool IsEmpty() const;

    /**
     * @brief returns the client data associated with this item
     **/
    wxClientData* GetClientObject(const wxDataViewItem& item) const;

    /**
     * @brief set the client data for an item. The item data will be freed by the model
     */
    void SetClientObject(const wxDataViewItem& item, wxClientData* data);

    /**
     * @brief returns the item columns data (as passed to AppendItem(..) / InsertItem(...))
     */
    wxVector<wxVariant> GetItemColumnsData(const wxDataViewItem& item) const;

    /**
     * @brief return true if this node is a container (i.e. has children)
     */
    virtual bool IsContainer(const wxDataViewItem& item) const;

    /**
     * @brief return true if item has children
     */
    virtual bool HasChildren(const wxDataViewItem& item) const;

    /**
     * @brief return the item parent. Return an invalid item if this item has no parent (item.IsOk() = false)
     */
    virtual wxDataViewItem GetParent(const wxDataViewItem& item) const;

    /**
     * @brief return the item's children as an array.
     * @return children count
     */
    virtual unsigned int GetChildren(const wxDataViewItem& item, wxDataViewItemArray& children) const;
};
#endif // __OpenResourceDialogModel_GUARD__H__
