#include "StdAfx.h"
#include "UIRootNode.h"
#include "UIWindow.h"
#include "UIManager.h"

/// 주의사항 : 
cUIRootNode::cUIRootNode( eUINodeType type )
: cUIContainer( type )
, mFontItemKeeper( 0 )
, mTipWindow( 0 )
{
	mpParent = 0;
	mID = 0;
	mpImage = 0;

//	mChildVisArray.Reserve( 30 );

	mRelativeRect.Set( 0, 0, GetScreenWidth(), GetScreenHeight() );
	mAbsoluteRect.Set( 0, 0, GetScreenWidth(), GetScreenHeight() );

	mVisible = true;
	mEnabled = true;

	mFontItemKeeper = new cUIFontItemKeeper;
}

/// 주의사항 : 
cUIRootNode::~cUIRootNode()
{
	SAFE_DELETE(mFontItemKeeper);

	mProcessList.Clear();
}

void cUIRootNode::HideAllChild( bool backupVis, cUINode* except )
{
	/// 가시 여부를 백업
	if( backupVis )
	{
		mChildVisArray.Clear();
		mChildVisArray.Reserve( mChildList.GetSize() );

		cChildList::cIterator i = mChildList.Begin();
		cChildList::cIterator iend = mChildList.End();

		for( ; i != iend; ++i )
		{
			cUINode* n = (cUINode*)(*i);

			if( n && n != except && n->IsBackupVisible() )
			{
				if( ((cUIWindow*)n)->IsModal() == false )
				{
					mChildVisArray.PushBack( cChildVis( n, n->IsVisible() ) );
				}
			}
		}
	}

	/// 숨김
	cChildList::cIterator i = mChildList.Begin();
	cChildList::cIterator iend = mChildList.End();

	for( ; i != iend; ++i )
	{
		cUINode* n = (cUINode*)(*i);

		if( n && n->IsKindof( eUINODE_WINDOW ) )
		{
			if( n != except && n->IsVisible() && n->IsBackupVisible() && ((cUIWindow*)n)->IsModal() == false )
			{
				cUIWindow* con = (cUIWindow*)n;
				con->Hide();	
			}
		}
		else
		{
			assert(0);
		}
	}

	///// 메세지 박스들만 앞으로 보내기
	//UIMAN->GotoFrontMsgBox();
}

void cUIRootNode::ShowAllChild( bool restoreVis, cUINode* except )
{
	/// 가시 여부를 복구
	if( restoreVis )
	{
		for( unsigned int i = 0, iend = mChildVisArray.GetSize(); i < iend; ++i )
		{
			cChildVis& pair = mChildVisArray[i];
			cUINode* n = (cUINode*)pair.mFirst;
			if( !n )
			{
				assert(0);
				continue;
			}

			if( n == except )
				continue;

			if( n->IsKindof( eUINODE_WINDOW ) )
			{
				if( n != mTipWindow )
				{
					cUIWindow* con = (cUIWindow*)n;
					( pair.mSecond ) ? con->Show() : con->Hide();
				}
			}
			else
			{
				assert(0);
			}
		}

		/// 특별 윈도우들 복구
		UIMAN->RestoreShow();
	}
	else
	{
		cChildList::cIterator i = mChildList.Begin();
		cChildList::cIterator iend = mChildList.End();

		for( ; i != iend; ++i )
		{
			cUINode* n = (cUINode*)(*i);

			if( n && n->IsKindof( eUINODE_WINDOW ) )
			{
				if( n != except && n->IsVisible() == false )
				{
					cUIWindow* con = (cUIWindow*)n;
					con->Show();	
				}
			}
			else
			{
				assert(0);
			}
		}
	}
}

//void cUIRootNode::AddVisibleArr( cUINode* node, bool visible )
//{
//	for( unsigned int i = 0; i < mChildVisArray.GetSize(); ++i )
//	{
//		cChildVis& pair = mChildVisArray[i];
//		cUINode* n = (cUINode*)pair.mFirst;
//
//		if( n && n == node )
//		{
//			pair.mSecond = visible;
//			return;
//		}
//	}
//
//	mChildVisArray.PushBack( cChildVis( node, visible ) );
//}


/// 주의사항 : 
bool cUIRootNode::Create( const cString&, cUIContainer*, unsigned int, bool )
{
	assert( 0 );

	return true;
}

/// 주의사항 : 
void cUIRootNode::UpdateRect()
{
	assert( 0 );
}

void cUIRootNode::UpdateSkin()
{
	/// 해상도 변화에따른 루트노드의 사이즈도 변경 
	cUIRect rc( 0, 0, GetScreenWidth(), GetScreenHeight() );
	mAbsoluteRect = rc;
	mRelativeRect = rc;

	/// 자식에 스킨 적용
	cChildList::cIterator i = mChildList.Begin();
	cChildList::cIterator end = mChildList.End();

	cUINode* n = 0;
	for( ; i != end; ++i )
	{
		n = (cUINode*)(*i);
		if( n )
			n->UpdateSkin();
	}
}


/// 주의사항 : 
bool cUIRootNode::SetSkin( const cUINodeSkin* )
{
	return true;
}

/// 주의사항 : 
bool cUIRootNode::IsValid() const
{
	return true;
}

/// 주의사항 : 
bool cUIRootNode::HandleEvent( const cUIEvent& )
{
	return true;
}


/// 주의사항 : 
void cUIRootNode::OnRender( cUIFontItemKeeper* )
{
	if( mVisible )
	{
		/// 자식 렌더링
		cChildList::cIterator i = mChildList.Begin();
		cChildList::cIterator end = mChildList.End();

		for( ; i != end; ++i )
		{
			cUINode* n = (cUINode*)(*i);

			if( n == mTipWindow )
				continue;

			if( n && n->IsVisible() == true )
				n->OnRender( mFontItemKeeper );
		}
		mFontItemKeeper->DrawAll();

		/// 팁 렌더링
		if( mTipWindow )
		{
			mTipWindow->OnRender( mFontItemKeeper );
			mFontItemKeeper->DrawAll();
		}
	}
}

/// 주의사항 : 
void cUIRootNode::OnProcess( unsigned long deltaTime, unsigned long accumTime )
{
	if( mVisible )
	{
		cProcessChildList::cIterator i = mProcessList.Begin();
		cProcessChildList::cIterator end = mProcessList.End();

		for( ; i != end; ++i )
		{
			cUINode* node = ( cUINode* )( *i );
			if( node )
			{
				node->OnProcess( deltaTime, accumTime );
			}
			else
			{
				assert(0);
			}
		}

/*
		/// 자식 렌더링
		cChildList::cIterator i = mChildList.Begin();
		cChildList::cIterator end = mChildList.End();

		for( ; i != end; ++i )
		{
			cUINode* node = ( cUINode* )( *i );
			if( node )
			{
				node->OnProcess( deltaTime, accumTime );
			}
			else
				assert(0);
		}

		if( mTipWindow )
		{
			mTipWindow->OnProcess( deltaTime, accumTime );
		}
*/
	}
}

cUIContainer* cUIRootNode::GetContainer( const cUIPos& pos ) const
{
	/// 화면상 맨 앞에서 뒤로 검사
	cChildList::cConstIterator i = (--mChildList.End());
	cChildList::cConstIterator end = (--mChildList.Begin());

	for( ; i != end; --i )
	{
		cUINode* n = (cUINode*)(*i);
		if( !n )
		{
			assert(0);
			return 0;
		}

		if( n->IsVisible() == false )
		{
			continue;
		}

		if( n->IsKindof(eUINODE_CONTAINER) )
		{
			if( n->ContainPoint( pos ) )
			{
				return (cUIContainer*)n;
			}
		}
	}

	return 0;
}

/// 윈도우를 닫는다.
bool cUIRootNode::Close()
{
	/// 자식갯수가 하나라도 있어야한다.
	if( mChildList.GetSize() > 0 )
	{
		/// 화면상 앞에서 뒤로 검사 
		cChildList::cConstIterator i = (--mChildList.End());
		cChildList::cConstIterator end = (--mChildList.Begin());
		
		for( ; i != end; --i )
		{
			////// node인데 자식인것들 따로 체크해보기 
			cUINode* n = (cUINode*)(*i);

			/// root 의 자식은 반드시 컨테이너여야 한다. 
			if( n && n->IsKindof( eUINODE_WINDOW ) )
			{
				cUIWindow* con = (cUIWindow*)n;

				/// 반드시 보여야하는 윈도우들만 빼고 처리한다 
				if( con && con->IsVisible() && con->IsHoldView() == false )
				{
					con->HideESC( true );
					return true;
				}
			}
		}
	}

	return false;
}

void cUIRootNode::NetUnLockAllUI()
{
	/// 자식갯수가 하나라도 있어야한다.
	if( mChildList.GetSize() > 0 )
	{
		/// 화면상 앞에서 뒤로 검사 
		cChildList::cConstIterator i = (--mChildList.End());
		cChildList::cConstIterator end = (--mChildList.Begin());

		for( ; i != end; --i )
		{
			////// node인데 자식인것들 따로 체크해보기 
			cUINode* n = (cUINode*)(*i);

			/// root 의 자식은 반드시 컨테이너여야 한다. 
			if( n && n->IsKindof( eUINODE_WINDOW ) )
			{
				cUIWindow* con = (cUIWindow*)n;

				if( con )
					con->NetUnLockAllUI();
			}
		}
	}
}

void cUIRootNode::AddProcessChild( cUINode* n )
{
	if( n->IsEnableProcess() )
		mProcessList.PushFront( n );

	if( n->IsKindof( eUINODE_CONTAINER ) == true )
	{
		cUIContainer* con = (cUIContainer*)n;
		tPointerList<void*>* plist = con->GetChildList();
		if( plist->IsEmpty() )
			return;

		tPointerList<void*>::cIterator i = plist->Begin();
		tPointerList<void*>::cIterator iend = plist->End();
		for( ; i != iend; ++i )
		{
			AddProcessChild( (cUINode*)(*i) );
		}
	}
}

void cUIRootNode::RemoveProcessChild( cUINode* n )
{
	if( n->IsEnableProcess() )
		mProcessList.Remove( n );

	if( n->IsKindof( eUINODE_CONTAINER ) == true )
	{
		cUIContainer* con = (cUIContainer*)n;
		tPointerList<void*>* plist = con->GetChildList();
		if( plist->IsEmpty() )
			return;

		tPointerList<void*>::cIterator i = plist->Begin();
		tPointerList<void*>::cIterator iend = plist->End();
		for( ; i != iend; ++i )
		{
			cUINode* p = (cUINode*)(*i);
			RemoveProcessChild( p );
		}
	}
}