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

#include "openresourcedialogmodel.h"

#include <wx/dvrenderers.h>
#include <wx/variant.h>

//////////////////////////////////////////
// Implementation
//////////////////////////////////////////

// -------------------------------------------------
// Help method
// -------------------------------------------------
wxVariant OpenResourceDialogModel::CreateIconTextVariant(const wxString& text, const wxBitmap& bmp)
{
    wxIcon icn;
    icn.CopyFromBitmap(bmp);
    wxDataViewIconText ict(text, icn);
    wxVariant v;
    v << ict;
    return v;
}

// -------------------------------------------------
// The model class
// -------------------------------------------------

OpenResourceDialogModel::OpenResourceDialogModel()
    : m_colCount(0)
{
}

OpenResourceDialogModel::~OpenResourceDialogModel()
{
    for(size_t i = 0; i < m_data.size(); ++i) {
        wxDELETE(m_data.at(i));
    }
    m_data.clear();
}

unsigned int OpenResourceDialogModel::GetChildren(const wxDataViewItem& item, wxDataViewItemArray& children) const
{
    if(item.GetID() == NULL) {
        // Root
        for(size_t i = 0; i < m_data.size(); ++i) {
            children.Add(wxDataViewItem(m_data.at(i)));
        }
        return children.size();
    }

    children.Clear();
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.m_pItem);
    if(node) {
        for(size_t i = 0; i < node->GetChildren().size(); ++i) {
            children.Add(wxDataViewItem(node->GetChildren().at(i)));
        }
    }
    return children.GetCount();
}

unsigned int OpenResourceDialogModel::GetColumnCount() const { return m_colCount; }

wxString OpenResourceDialogModel::GetColumnType(unsigned int col) const
{
    if(!m_data.empty() && m_data.at(0)->GetData().size() > col) {
        return m_data.at(0)->GetData().at(col).GetType();
    }
    return "string";
}

wxDataViewItem OpenResourceDialogModel::GetParent(const wxDataViewItem& item) const
{
    if(IsEmpty()) {
        return wxDataViewItem(NULL);
    }

    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.m_pItem);
    if(node) {
        return wxDataViewItem(node->GetParent());
    }
    return wxDataViewItem(NULL);
}

bool OpenResourceDialogModel::IsContainer(const wxDataViewItem& item) const
{
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.m_pItem);
    if(node) {
        return node->IsContainer();
    }
    return false;
}

void OpenResourceDialogModel::GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const
{
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.m_pItem);
    if(node && node->GetData().size() > col) {
        variant = node->GetData().at(col);
    }
}
wxDataViewItem OpenResourceDialogModel::DoAppendItem(const wxDataViewItem& parent, const wxVector<wxVariant>& data,
                                                     bool isContainer, wxClientData* clientData)
{
    OpenResourceDialogModel_Item* parentNode = reinterpret_cast<OpenResourceDialogModel_Item*>(parent.m_pItem);
    DoChangeItemType(parent, true);

    OpenResourceDialogModel_Item* child = new OpenResourceDialogModel_Item();
    child->SetIsContainer(isContainer);
    child->SetClientObject(clientData);
    child->SetData(data);
    if(parentNode) {
        parentNode->AddChild(child);

    } else {
        m_data.push_back(child);
    }

    return wxDataViewItem(child);
}

wxDataViewItem OpenResourceDialogModel::DoInsertItem(const wxDataViewItem& insertBeforeMe,
                                                     const wxVector<wxVariant>& data, bool isContainer,
                                                     wxClientData* clientData)
{
    OpenResourceDialogModel_Item* child = new OpenResourceDialogModel_Item();
    child->SetIsContainer(isContainer);
    child->SetClientObject(clientData);
    child->SetData(data);

    // find the location where to insert the new item
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(insertBeforeMe.m_pItem);
    if(!node)
        return wxDataViewItem();

    wxVector<OpenResourceDialogModel_Item*>::iterator where = std::find(m_data.begin(), m_data.end(), node);

    if(where != m_data.end()) {
        // top level item
        m_data.insert(where, child);

    } else {

        if(!node->GetParent())
            return wxDataViewItem();

        child->SetParent(node->GetParent());
        where = std::find(node->GetParent()->GetChildren().begin(), node->GetParent()->GetChildren().end(), node);
        if(where == node->GetParent()->GetChildren().end()) {
            node->GetParent()->GetChildren().push_back(child);

        } else {
            node->GetParent()->GetChildren().insert(where, child);
        }
    }

    return wxDataViewItem(child);
}

wxDataViewItem OpenResourceDialogModel::AppendItem(const wxDataViewItem& parent, const wxVector<wxVariant>& data,
                                                   wxClientData* clientData)
{
    wxDataViewItem ch = DoAppendItem(parent, data, false, clientData);
    ItemAdded(parent, ch);
    return ch;
}

wxDataViewItemArray OpenResourceDialogModel::AppendItems(const wxDataViewItem& parent,
                                                         const wxVector<wxVector<wxVariant>>& data)
{
    wxDataViewItemArray items;
    for(size_t i = 0; i < data.size(); ++i) {
        items.push_back(DoAppendItem(parent, data.at(i), false, NULL));
    }
    ItemsAdded(parent, items);
    return items;
}

bool OpenResourceDialogModel::SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col)
{
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.m_pItem);
    if(node && node->GetData().size() > col) {
        node->GetData().at(col) = variant;
    }
    return true;
}

void OpenResourceDialogModel::DeleteItem(const wxDataViewItem& item)
{
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.m_pItem);
    if(node) {

        OpenResourceDialogModel_Item* parent = node->GetParent();
        wxDataViewItem parentItem(parent);
        ItemDeleted(parentItem, item);

        // this will also remove it from its model parent children list
        if(parent == NULL) {
            // root item, remove it from the roots array
            wxVector<OpenResourceDialogModel_Item*>::iterator where = std::find(m_data.begin(), m_data.end(), node);
            if(where != m_data.end()) {
                m_data.erase(where);
            }
        }

        // If there are no more children, change the item back to 'normal'
        if(parent && parent->GetChildren().empty())
            DoChangeItemType(parentItem, false);

        wxDELETE(node);
    }

    if(IsEmpty())
        Cleared();
}

void OpenResourceDialogModel::DeleteItems(const wxDataViewItem& parent, const wxDataViewItemArray& items)
{
    // sanity
    for(size_t i = 0; i < items.GetCount(); ++i) {
        OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(items.Item(i).m_pItem);
        wxUnusedVar(node);
        wxASSERT(node && node->GetParent() == parent.m_pItem);
        DeleteItem(items.Item(i));
    }
}

void OpenResourceDialogModel::Clear()
{
    wxVector<OpenResourceDialogModel_Item*> roots = m_data;
    wxVector<OpenResourceDialogModel_Item*>::iterator iter = roots.begin();
    for(; iter != roots.end(); ++iter) {
        DeleteItem(wxDataViewItem(*iter));
    }
    m_data.clear();
    Cleared();
}

bool OpenResourceDialogModel::IsEmpty() const { return m_data.empty(); }

wxClientData* OpenResourceDialogModel::GetClientObject(const wxDataViewItem& item) const
{
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.GetID());
    if(node) {
        return node->GetClientObject();
    }
    return NULL;
}

void OpenResourceDialogModel::SetClientObject(const wxDataViewItem& item, wxClientData* data)
{
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.GetID());
    if(node) {
        node->SetClientObject(data);
    }
}

void OpenResourceDialogModel::UpdateItem(const wxDataViewItem& item, const wxVector<wxVariant>& data)
{
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.GetID());
    if(node) {
        node->SetData(data);
        ItemChanged(item);
    }
}

wxDataViewItem OpenResourceDialogModel::InsertItem(const wxDataViewItem& insertBeforeMe,
                                                   const wxVector<wxVariant>& data, wxClientData* clientData)
{
    wxDataViewItem ch = DoInsertItem(insertBeforeMe, data, false, clientData);
    if(ch.IsOk()) {
        OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(ch.GetID());
        ItemAdded(wxDataViewItem(node->GetParent()), ch);
    }
    return ch;
}

wxVector<wxVariant> OpenResourceDialogModel::GetItemColumnsData(const wxDataViewItem& item) const
{
    if(!item.IsOk())
        return wxVector<wxVariant>();

    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.GetID());
    if(!node) {
        return wxVector<wxVariant>();
    }
    return node->GetData();
}

bool OpenResourceDialogModel::HasChildren(const wxDataViewItem& item) const
{
    if(!item.IsOk())
        return false;

    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.GetID());
    if(!node) {
        return false;
    }
    return !node->GetChildren().empty();
}

void OpenResourceDialogModel::DoChangeItemType(const wxDataViewItem& item, bool changeToContainer)
{
    OpenResourceDialogModel_Item* node = reinterpret_cast<OpenResourceDialogModel_Item*>(item.GetID());
    if(!node)
        return;

    if((changeToContainer && !node->IsContainer()) || // change an item from non-container to container type
       (!changeToContainer && node->IsContainer())) { // change an item from container to non-container type
#if defined(__WXGTK__) || defined(__WXMAC__)
        // change the item to container type:
        // 1st we need to delete it
        ItemDeleted(wxDataViewItem(node->GetParent()), item);

        // update the node type
        node->SetIsContainer(changeToContainer);
        ItemAdded(wxDataViewItem(node->GetParent()), item);
#else
        node->SetIsContainer(changeToContainer);
#endif
    }
}
