#include "StdAfx.h"
#include "TreeView.h"


namespace ui
{

TreeNode::TreeNode() :
	m_bExpand(true),
	m_pTreeView(nullptr),
	m_pParentTreeNode(nullptr),
	m_iDepth(ROOT_NODE_DEPTH),
	m_aTreeNodes()
{
	
}

bool TreeNode::IsVisible() const
{
	return ListContainerElement::IsVisible()
		&& (!m_pParentTreeNode || (m_pParentTreeNode && m_pParentTreeNode->IsExpand() && m_pParentTreeNode->IsVisible()));
}

void TreeNode::SetInternVisible(bool bVisible)
{
	Control::SetInternVisible(bVisible);
	if (m_items.empty()) return;

	for (auto it = m_items.begin(); it != m_items.end(); it++)
	{
		auto pControl = *it;
		// 控制子控件显示状态
		// InternVisible状态应由子控件自己控制
		pControl->SetInternVisible(Control::IsVisible());
	}
}

void TreeNode::SetWindow(Window* pManager, Box* pParent, bool bInit)
{
	for (auto it = m_aTreeNodes.begin(); it != m_aTreeNodes.end(); it++)
	{
		(*it)->SetWindow(pManager, this, bInit);
	}

	ListContainerElement::SetWindow(pManager, pParent, bInit);
}

void TreeNode::SetTreeView(TreeView* pTreeView)
{
	m_pTreeView = pTreeView;
}

bool TreeNode::OnClickItem(EventArgs* pMsg)
{
	TreeNode* pItem = static_cast<TreeNode*>(pMsg->pSender);
	pItem->SetExpand(!pItem->IsExpand());

	return true;
}

TreeNode* TreeNode::GetParentNode()
{
	return m_pParentTreeNode;
}

void TreeNode::SetParentNode(TreeNode* pParentTreeNode)
{
	m_pParentTreeNode = pParentTreeNode;
}

bool TreeNode::AddChildNode(TreeNode* pTreeNode)
{
	return AddChildNodeAt(pTreeNode, GetChildNodeCount());
}

bool TreeNode::AddChildNodeAt(TreeNode* pTreeNode, std::size_t iIndex)
{
	if( iIndex < 0 || iIndex > m_aTreeNodes.size() ) return false;
	m_aTreeNodes.insert(m_aTreeNodes.begin() + iIndex, pTreeNode);
		
	pTreeNode->m_iDepth = m_iDepth + 1;
	pTreeNode->SetParentNode(this);
	pTreeNode->SetTreeView(m_pTreeView);
	if( m_pWindow != NULL ) m_pWindow->InitControls(pTreeNode, NULL);
	pTreeNode->OnEvent[kEventClick] += nbase::Bind(&TreeNode::OnClickItem, this, std::placeholders::_1);

	UiRect padding = m_pLayout->GetPadding();
	int nodeIndex = -1;
	if (m_iDepth != ROOT_NODE_DEPTH) {
		nodeIndex = GetIndex();
		padding.left += m_pTreeView->GetIndent();
	}
	pTreeNode->m_pLayout->SetPadding(padding);

	std::size_t nGlobalIndex = iIndex;
	for (std::size_t i = 0; i < iIndex; i++)
	{
		nGlobalIndex += ((TreeNode*)m_aTreeNodes[i])->GetDescendantNodeCount();
	}

	return m_pTreeView->ListBox::AddAt(pTreeNode, (int)(nodeIndex + nGlobalIndex + 1));
}

bool TreeNode::RemoveChildNodeAt(std::size_t iIndex)
{
	if (iIndex < 0 || iIndex >= m_aTreeNodes.size()) {
		return false;
	}

	TreeNode* pTreeNode = ((TreeNode*)m_aTreeNodes[iIndex]);
	m_aTreeNodes.erase(m_aTreeNodes.begin() + iIndex);

	return pTreeNode->RemoveSelf();
}

bool TreeNode::RemoveChildNode(TreeNode* pTreeNode)
{
	auto it = std::find(m_aTreeNodes.begin(), m_aTreeNodes.end(), pTreeNode);
	if (it == m_aTreeNodes.end()) {
		return false;
	}
		
	int iIndex = it - m_aTreeNodes.begin();
	return RemoveChildNodeAt(iIndex);
}
	
void TreeNode::RemoveAllChildNode()
{
	while (m_aTreeNodes.size() > 0)
	{
		RemoveChildNodeAt(0);
	}
}

bool TreeNode::RemoveSelf()
{
	for( auto it = m_aTreeNodes.begin(); it != m_aTreeNodes.end(); it++ ) 
	{
		(*it)->RemoveSelf();
	}
	m_aTreeNodes.clear();

	if (m_iDepth != ROOT_NODE_DEPTH) {
		return m_pTreeView->ListBox::RemoveAt(GetIndex());
	}

	return false;
}

int TreeNode::GetDescendantNodeCount()
{
	int nodeCount = (int)GetChildNodeCount();
	for( auto it = m_aTreeNodes.begin(); it != m_aTreeNodes.end(); it++ )
	{
		nodeCount += (*it)->GetDescendantNodeCount();
	}

	return nodeCount;
}

std::size_t TreeNode::GetChildNodeCount()
{
	return m_aTreeNodes.size();
}
	
TreeNode* TreeNode::GetChildNode(std::size_t iIndex)
{
	if( iIndex < 0 || iIndex >= m_aTreeNodes.size() ) return NULL;
	return static_cast<TreeNode*>(m_aTreeNodes[iIndex]);
}
	
int TreeNode::GetChildNodeIndex(TreeNode* pTreeNode)
{
	auto it = std::find(m_aTreeNodes.begin(), m_aTreeNodes.end(), pTreeNode);
	if (it == m_aTreeNodes.end()) {
		return -1;
	}
	return it - m_aTreeNodes.begin();
}

bool TreeNode::IsExpand() const
{
	return m_bExpand;
}

void TreeNode::SetExpand(bool bExpand)
{
	if(m_bExpand == bExpand) {
		return;
	}
	m_bExpand = bExpand;
	m_pTreeView->Arrange();
}

int TreeNode::GetDepth()
{
	return m_iDepth;
}

TreeView::TreeView() :
	ListBox(new VLayout),
	m_iIndent(0),
	m_rootNode()
{
	m_rootNode.reset(new TreeNode());
	m_rootNode->SetTreeView(this);
}

void TreeView::SetAttribute(const std::wstring& strName, const std::wstring& strValue)
{
	if( strName == _T("indent") ) {
		SetIndent(_ttoi(strValue.c_str()));
	}
	else {
		ListBox::SetAttribute(strName, strValue);
	}
}

bool TreeView::Add(Control* pControl)
{
	ASSERT(FALSE);
	return true;
}

bool TreeView::AddAt(Control* pControl, std::size_t iIndex)
{
	ASSERT(FALSE);
	return true;
}

bool TreeView::Remove(Control* pControl)
{
	ASSERT(FALSE);
	return true;
}

bool TreeView::RemoveAt(std::size_t iIndex)
{
	ASSERT(FALSE);
	return true;
}

void TreeView::RemoveAll()
{
	ASSERT(FALSE);
}

void TreeView::SetWindow(Window* pManager, Box* pParent, bool bInit)
{
	ListBox::SetWindow(pManager, pParent, bInit);
	if (NULL != pParent) m_rootNode->SetWindow(pManager, pParent, bInit);
}

}