#include "Mix/Tool/CLR/Core/Dynamics/FlagsGenerator.h"

namespace Mix{ namespace Tool{ namespace Dynamics{

////////////////////////////////////////////////////////////////////////////////////////////////////
// FlagsGenerator::ErrorList
////////////////////////////////////////////////////////////////////////////////////////////////////

FlagsGenerator::ErrorList::ErrorList( System::Collections::Generic::List<System::String^>^ nameList ) :
m_NameList( nameList ),
m_List( gcnew System::Collections::Generic::List<System::String^>() )
{
	if( nameList == nullptr )
	{
		throw gcnew System::ArgumentNullException( L"nameList" );
	}
}

void FlagsGenerator::ErrorList::Reset( void )
{
	m_List->Clear();
}

void FlagsGenerator::ErrorList::Add( System::String^ name )
{
	if( m_List->Contains( name ) == false )
	{
		m_List->Add( name );
	}
}

int FlagsGenerator::ErrorList::Count::get( void )
{
	return m_List->Count;
}

System::String^ FlagsGenerator::ErrorList::default::get( int index )
{
	try
	{
		return m_List[index];
	}
	catch( System::Exception^ )
	{
		throw;
	}
}

bool FlagsGenerator::ErrorList::Remove( System::String^ name )
{
	if( m_List->Contains( name ) == true )
	{
		return m_List->Remove( name );
	}

	return false;
}

void FlagsGenerator::ErrorList::Clear( void )
{
	for each ( System::String^ name in m_List )
	{
		m_NameList->Remove( name );
	}

	m_List->Clear();
}

System::Collections::IEnumerator^ FlagsGenerator::ErrorList::GetEnumerator( void )
{
	return m_List->GetEnumerator();
}

System::Collections::Generic::IEnumerator<System::String^>^ FlagsGenerator::ErrorList::GetEnumerator_Generic( void )
{
	return m_List->GetEnumerator();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// FlagsGenerator
////////////////////////////////////////////////////////////////////////////////////////////////////

FlagsGenerator::FlagsGenerator( Mix::Tool::Utility::BindingItemCollection<int>^ owner ) :
m_Owner( owner ),
m_NameList( gcnew System::Collections::Generic::List<System::String^>() ),
m_ErrorList( nullptr ),
m_Value( 0 ),
ValueChanged( nullptr )
{
	if( owner == nullptr )
	{
		throw gcnew System::ArgumentNullException( L"owner" );
	}

	m_ErrorList = gcnew FlagsGenerator::ErrorList( m_NameList );
	m_Owner->ListChanged += gcnew System::ComponentModel::ListChangedEventHandler( this, &FlagsGenerator::ListChanged );
}

FlagsGenerator::~FlagsGenerator( void )
{
	if( m_Owner != nullptr )
	{
		m_Owner->ListChanged -= gcnew System::ComponentModel::ListChangedEventHandler( this, &FlagsGenerator::ListChanged );
	}
}

int FlagsGenerator::Count::get( void )
{
	return m_NameList->Count;
}

System::String^ FlagsGenerator::default::get( int index )
{
	try
	{
		return m_NameList[index];
	}
	catch( System::Exception^ )
	{
		throw;
	}
}

int FlagsGenerator::Value::get( void )
{
	return m_Value;
}

void FlagsGenerator::Clear( void )
{
	m_NameList->Clear();
	m_ErrorList->Clear();
}

void FlagsGenerator::Add( System::String^ name )
{
	if( m_NameList->Contains( name ) == false )
	{
		m_NameList->Add( name );
		Update();
	}
}

bool FlagsGenerator::Remove( System::String^ name )
{
	bool ret = false;

	if( m_ErrorList->Remove( name ) == false )
	{
		//エラーリストに存在しなく、削除に成功した場合は、m_Value を更新する
		ret = m_NameList->Remove( name );
		if( ret == true )
		{
			Update();
		}
	}
	else
	{
		//エラーリストに存在しているので、ネームリストからも削除されている
		//m_Value は更新する必要はない
		ret = true;
	}

	return ret;
}

bool FlagsGenerator::Contains( System::String^ name )
{
	return m_NameList->Contains( name );
}

void FlagsGenerator::Update( void )
{
	m_ErrorList->Reset();
	m_Value = 0;

	for each ( System::String^ name in m_NameList )
	{
		int index = m_Owner->FindByName( name );
		if( index >= 0 )
		{
			int number;

			if( int::TryParse( m_Owner[index]->Value, number ) == true )
			{
				if( number > 0 )
				{
					m_Value = m_Value | ( 1 << ( number - 1 ) );
				}
				else
				{
					m_ErrorList->Add( name );
				}
			}
/*
			int number = int::Parse( m_Owner[index]->Value );
			if( number > 0 )
			{
				m_Value = m_Value | ( 1 << ( number - 1 ) );
			}
			else
			{
				m_ErrorList->Add( name );
			}
*/		}
	}

	if( ValueChanged != nullptr )
	{
		ValueChanged( this, gcnew System::EventArgs() );
	}
}

void FlagsGenerator::ListChanged( System::Object^ sender, System::ComponentModel::ListChangedEventArgs^ e )
{
	Update();
}

System::Collections::IEnumerator^ FlagsGenerator::GetEnumerator( void )
{
	return m_NameList->GetEnumerator();
}

System::Collections::Generic::IEnumerator<System::String^>^ FlagsGenerator::GetEnumerator_Generic( void )
{
	return m_NameList->GetEnumerator();
}

}}}
