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

#ifndef __XDebugLocalsViewModel_GUARD__H__
#define __XDebugLocalsViewModel_GUARD__H__

#include <wx/variant.h>
#include <wx/dataview.h>
#include <algorithm>
#include <wx/clntdata.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 XDebugLocalsViewModel_Item class, simply use:
 * @code
 * XDebugLocalsViewModel_Item* itemData = reinterpret_cast<XDebugLocalsViewModel_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 XDebugLocalsViewModel_Item
{
protected:
    wxVector<wxVariant>        m_data;
    XDebugLocalsViewModel_Item*           m_parent;
    wxVector<XDebugLocalsViewModel_Item*> m_children;
    bool                       m_isContainer;
    wxClientData*              m_clientData;

public:
    XDebugLocalsViewModel_Item()
        : m_parent(NULL)
        , m_isContainer(false)
        , m_clientData(NULL)
    {}
    virtual ~XDebugLocalsViewModel_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<XDebugLocalsViewModel_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(XDebugLocalsViewModel_Item* child) {
        wxVector<XDebugLocalsViewModel_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(XDebugLocalsViewModel_Item* child) {
        wxVector<XDebugLocalsViewModel_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(XDebugLocalsViewModel_Item* child) {
        m_children.push_back(child);
        child->m_parent = this;
    }

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

    // Setters / Getters
    void SetChildren(const wxVector<XDebugLocalsViewModel_Item*>& children) {
        this->m_children = children;
    }
    void SetData(const wxVector<wxVariant>& data) {
        this->m_data = data;
    }
    void SetParent(XDebugLocalsViewModel_Item* parent) {
        this->m_parent = parent;
    }
    const wxVector<XDebugLocalsViewModel_Item*>& GetChildren() const {
        return m_children;
    }
    wxVector<XDebugLocalsViewModel_Item*>& GetChildren() {
        return m_children;
    }
    const wxVector<wxVariant>& GetData() const {
        return m_data;
    }
    wxVector<wxVariant>& GetData() {
        return m_data;
    }
    XDebugLocalsViewModel_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 XDebugLocalsViewModel : public wxDataViewModel
{
protected:
    wxVector<XDebugLocalsViewModel_Item*> m_data;
    unsigned int m_colCount;

public:
    XDebugLocalsViewModel();
    virtual ~XDebugLocalsViewModel();
    
    /**
     * @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<XDebugLocalsViewModel_Item*> data) {
        this->m_data = data;
    }
    unsigned int GetColCount() const {
        return m_colCount;
    }
    const wxVector<XDebugLocalsViewModel_Item*>& GetData() const {
        return m_data;
    }
    wxVector<XDebugLocalsViewModel_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 // __XDebugLocalsViewModel_GUARD__H__
