#include "Mix/Tool/Win32/Core/Graphics/MotionCurve.h"

#include <algorithm>
#include "Mix/Tool/Win32/Core/Graphics/ObjectModel.h"

namespace Mix{ namespace Tool{ namespace Win32{ namespace Graphics{

MotionCurve::MotionCurve( int index ) :
m_Index( index ),
m_LinkNodeName( L"" ),
m_bEnabled( true )
{
}

MotionCurve::MotionCurve( int index, const wchar_t* pLinkNodeName ) :
m_Index( index ),
m_LinkNodeName( pLinkNodeName ),
m_bEnabled( true )
{
}

MotionCurve::~MotionCurve( void )
{
}

void MotionCurve::ReserveKeyList( unsigned int sKeyCount, unsigned int rKeyCount, unsigned int tKeyCount )
{
	m_ScalingKeyList.reserve( sKeyCount );
	m_RotationKeyList.reserve( rKeyCount );
	m_TranslationKeyList.reserve( tKeyCount );
}

void MotionCurve::AddScalingKey( int time, const D3DXVECTOR3& value )
{
	m_ScalingKeyList.push_back( Mix::Tool::Win32::Graphics::VECTOR_KEY( static_cast<float>( time ), value ) );
}

unsigned int MotionCurve::GetScalingKeyCount( void ) const
{
	return m_ScalingKeyList.size();
}

const Mix::Tool::Win32::Graphics::VECTOR_KEY& MotionCurve::GetScalingKey( int index ) const
{
	return m_ScalingKeyList[index];
}

void MotionCurve::ClearScalingKey( void )
{
	m_ScalingKeyList.clear();
}

void MotionCurve::AddRotationKey( int time, const D3DXQUATERNION& value )
{
	D3DXQUATERNION normValue;

	::D3DXQuaternionNormalize( &normValue, &value );
	m_RotationKeyList.push_back( Mix::Tool::Win32::Graphics::QUATERNION_KEY( static_cast<float>( time ), normValue ) );
}

unsigned int MotionCurve::GetRotationKeyCount( void ) const
{
	return m_RotationKeyList.size();
}

const Mix::Tool::Win32::Graphics::QUATERNION_KEY& MotionCurve::GetRotationKey( int index ) const
{
	return m_RotationKeyList[index];
}

void MotionCurve::ClearRotationKey( void )
{
	m_RotationKeyList.clear();
}

void MotionCurve::AddTranslationKey( int time, const D3DXVECTOR3& value )
{
	m_TranslationKeyList.push_back( Mix::Tool::Win32::Graphics::VECTOR_KEY( static_cast<float>( time ), value ) );
}

void MotionCurve::SetTranslationValue( unsigned int index, const D3DXVECTOR3& value )
{
	m_TranslationKeyList[index].value = value;
}

unsigned int MotionCurve::GetTranslationKeyCount( void ) const
{
	return m_TranslationKeyList.size();
}

const Mix::Tool::Win32::Graphics::VECTOR_KEY& MotionCurve::GetTranslationKey( int index ) const
{
	return m_TranslationKeyList[index];
}

void MotionCurve::ClearTranslationKey( void )
{
	m_TranslationKeyList.clear();
}

float MotionCurve::GetLastTime( void )
{
	float lastTime = 0;

	for( Mix::Tool::Win32::Graphics::VectorKeyList::iterator it = m_ScalingKeyList.begin(); it != m_ScalingKeyList.end(); ++it )
	{
		if( lastTime < ( *it ).time ) { lastTime = ( *it ).time; }
	}

	for( Mix::Tool::Win32::Graphics::QuaternionKeyList::iterator it = m_RotationKeyList.begin(); it != m_RotationKeyList.end(); ++it )
	{
		if( lastTime < ( *it ).time ) { lastTime = ( *it ).time; }
	}

	for( Mix::Tool::Win32::Graphics::VectorKeyList::iterator it = m_TranslationKeyList.begin(); it != m_TranslationKeyList.end(); ++it )
	{
		if( lastTime < ( *it ).time ) { lastTime = ( *it ).time; }
	}

	return lastTime;
}

D3DXVECTOR3 MotionCurve::GetScaling( float time )
{
	if( m_ScalingKeyList.size() == 0 )
	{
		return D3DXVECTOR3( 1.0f, 1.0f, 1.0f );
	}

	const Mix::Tool::Win32::Graphics::VECTOR_KEY& firstKey = m_ScalingKeyList.front();
	const Mix::Tool::Win32::Graphics::VECTOR_KEY& lastKey = m_ScalingKeyList.back();

	if( firstKey.time >= time )
	{
		return firstKey.value;
	}
	else if( lastKey.time <= time )
	{
		return lastKey.value;
	}

	Mix::Tool::Win32::Graphics::VectorKeyList::iterator it = std::upper_bound( m_ScalingKeyList.begin(), m_ScalingKeyList.end(), time, Mix::Tool::Win32::Graphics::VECTOR_KEY() );
	if( ( *it ).time == time )
	{
		return ( *it ).value;
	}

	const Mix::Tool::Win32::Graphics::VECTOR_KEY& prevKey = ( *( it - 1 ) );
	const Mix::Tool::Win32::Graphics::VECTOR_KEY& nextKey = ( *it );
	const D3DXVECTOR3& prevValue = prevKey.value;
	const D3DXVECTOR3& nextValue = nextKey.value;

	float ratio = MIX_FLOAT_DIV( ( time - prevKey.time ), ( nextKey.time - prevKey.time ) );

	return prevValue + ( ( nextValue - prevValue ) * ratio );
}

D3DXQUATERNION MotionCurve::GetRotation( float time )
{
	if( m_RotationKeyList.size() == 0 )
	{
		return D3DXQUATERNION( 0.0f, 0.0f, 0.0f, 1.0f );
	}

	const Mix::Tool::Win32::Graphics::QUATERNION_KEY& firstKey = m_RotationKeyList.front();
	const Mix::Tool::Win32::Graphics::QUATERNION_KEY& lastKey = m_RotationKeyList.back();

	if( firstKey.time >= time )
	{
		return firstKey.value;
	}
	else if( lastKey.time <= time )
	{
		return lastKey.value;
	}

	Mix::Tool::Win32::Graphics::QuaternionKeyList::iterator it = std::upper_bound( m_RotationKeyList.begin(), m_RotationKeyList.end(), time, Mix::Tool::Win32::Graphics::QUATERNION_KEY() );
	if( ( *it ).time == time )
	{
		return ( *it ).value;
	}

	const Mix::Tool::Win32::Graphics::QUATERNION_KEY& prevKey = ( *( it - 1 ) );
	const Mix::Tool::Win32::Graphics::QUATERNION_KEY& nextKey = ( *it );
	const D3DXQUATERNION& prevValue = prevKey.value;
	const D3DXQUATERNION& nextValue = nextKey.value;

	float ratio = MIX_FLOAT_DIV( ( time - prevKey.time ), ( nextKey.time - prevKey.time ) );

	D3DXQUATERNION ret;

	return *( D3DXQuaternionSlerp( &ret, &prevValue, &nextValue, ratio ) );
}

D3DXVECTOR3 MotionCurve::GetTranslation( float time )
{
	if( m_TranslationKeyList.size() == 0 )
	{
		return D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
	}

	const Mix::Tool::Win32::Graphics::VECTOR_KEY& firstKey = m_TranslationKeyList.front();
	const Mix::Tool::Win32::Graphics::VECTOR_KEY& lastKey = m_TranslationKeyList.back();

	if( firstKey.time >= time )
	{
		return firstKey.value;
	}
	else if( lastKey.time <= time )
	{
		return lastKey.value;
	}

	Mix::Tool::Win32::Graphics::VectorKeyList::iterator it = std::upper_bound( m_TranslationKeyList.begin(), m_TranslationKeyList.end(), time, Mix::Tool::Win32::Graphics::VECTOR_KEY() );
	if( ( *it ).time == time )
	{
		return ( *it ).value;
	}

	const Mix::Tool::Win32::Graphics::VECTOR_KEY& prevKey = ( *( it - 1 ) );
	const Mix::Tool::Win32::Graphics::VECTOR_KEY& nextKey = ( *it );
	const D3DXVECTOR3& prevValue = prevKey.value;
	const D3DXVECTOR3& nextValue = nextKey.value;

	float ratio = MIX_FLOAT_DIV( ( time - prevKey.time ), ( nextKey.time - prevKey.time ) );

	return prevValue + ( ( nextValue - prevValue ) * ratio );
}

int MotionCurve::GetIndex( void ) const
{
	return m_Index;
}

const wchar_t* MotionCurve::GetLinkNodeName( void ) const
{
	return m_LinkNodeName.c_str();
}

void MotionCurve::SetEnabled( bool state )
{
	m_bEnabled = state;
}

bool MotionCurve::GetEnabled( void ) const
{
	return m_bEnabled;
}

Mix::Tool::Win32::Object::TYPE MotionCurve::GetType( void ) const
{
	return Mix::Tool::Win32::Object::GRAPHICS__MOTION_CURVE;
}

/*
void MotionCurve::Finish( Mix::Tool::Win32::Graphics::ObjectModel* pObjectModel )
{
	if( pObjectModel == NULL )
	{
		return;
	}

	const Mix::Tool::Win32::Graphics::ObjectModel::NODE* pNode = pObjectModel->GetNode( m_LinkNodeName.c_str() );
	if( pNode == NULL )
	{
		return;
	}

	const D3DXVECTOR3& defScale = pNode->defLocalScaling;
	const D3DXQUATERNION& defRotation = pNode->defLocalRotation;
	const D3DXVECTOR3 defTranslation = pNode->defLocalTranslation;

	m_bEnabled = false;

	for( MotionCurve::ScalingKeyList::iterator it = m_ScalingKeyList.begin(); ( it != m_ScalingKeyList.end() ) && ( m_bEnabled == false ); ++it )
	{
		const Mix::Tool::Win32::Graphics::SCALING_KEY& key = ( *it );

		if( ( MIX_FLOAT_NOT_EQUAL( key.value.x, defScale.x ) == true ) ||
			( MIX_FLOAT_NOT_EQUAL( key.value.y, defScale.y ) == true ) ||
			( MIX_FLOAT_NOT_EQUAL( key.value.z, defScale.z ) == true ) )
		{
			m_bEnabled = true;
		}
	}

	for( MotionCurve::RotationKeyList::iterator it = m_RotationKeyList.begin(); ( it != m_RotationKeyList.end() ) && ( m_bEnabled == false ); ++it )
	{
		const Mix::Tool::Win32::Graphics::ROTATION_KEY& key = ( *it );

		if( ( MIX_FLOAT_NOT_EQUAL( key.value.x, defRotation.x ) == true ) ||
			( MIX_FLOAT_NOT_EQUAL( key.value.y, defRotation.y ) == true ) ||
			( MIX_FLOAT_NOT_EQUAL( key.value.z, defRotation.z ) == true ) ||
			( MIX_FLOAT_NOT_EQUAL( key.value.w, defRotation.w ) == true ) )
		{
			m_bEnabled = true;
		}
	}

	for( MotionCurve::TranslationKeyList::iterator it = m_TranslationKeyList.begin(); ( it != m_TranslationKeyList.end() ) && ( m_bEnabled == false ); ++it )
	{
		const Mix::Tool::Win32::Graphics::TRANSLATION_KEY& key = ( *it );

		if( ( MIX_FLOAT_NOT_EQUAL( key.value.x, defTranslation.x ) == true ) ||
			( MIX_FLOAT_NOT_EQUAL( key.value.y, defTranslation.y ) == true ) ||
			( MIX_FLOAT_NOT_EQUAL( key.value.z, defTranslation.z ) == true ) )
		{
			m_bEnabled = true;
		}
	}
}
*/
/*
bool MotionCurve::Read( Mix::Tool::Win32::File::InputStream& input )
{
	MotionCurve::MC_DESC desc;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 解放
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_LinkNodeName = L"";
	m_ScalingKeyList.clear();
	m_RotationKeyList.clear();
	m_TranslationKeyList.clear();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ヘッダ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( input.Read( &desc, sizeof( desc ) ) == false )
	{
		return false;
	}

	m_LinkNodeName = desc.linkNodeName;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// スケーリングキーリスト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	{
		std::vector<MotionCurve::MC_S_KEY> readList;
		std::vector<MotionCurve::MC_S_KEY>::iterator it_begin;
		std::vector<MotionCurve::MC_S_KEY>::iterator it_end;
		std::vector<MotionCurve::MC_S_KEY>::iterator it;

		readList.resize( desc.sKeyCount );
		it_begin = readList.begin();
		it_end = readList.end();

		if( input.Read( &( readList[0] ), sizeof( MotionCurve::MC_S_KEY ) * desc.sKeyCount ) == false )
		{
			return false;
		}

		m_ScalingKeyList.reserve( desc.sKeyCount );

		for( it = it_begin; it != it_end; ++it )
		{
			const MotionCurve::MC_S_KEY* pSrc = &( *it );
			Mix::Tool::Win32::Graphics::SCALING_KEY dst;

			dst.time = pSrc->time;
			dst.value.x = pSrc->value[0];
			dst.value.y = pSrc->value[1];
			dst.value.z = pSrc->value[2];

			m_ScalingKeyList.push_back( dst );
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ローテーションキーリスト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	{
		std::vector<MotionCurve::MC_R_KEY> readList;
		std::vector<MotionCurve::MC_R_KEY>::iterator it_begin;
		std::vector<MotionCurve::MC_R_KEY>::iterator it_end;
		std::vector<MotionCurve::MC_R_KEY>::iterator it;

		readList.resize( desc.rKeyCount );
		it_begin = readList.begin();
		it_end = readList.end();

		if( input.Read( &( readList[0] ), sizeof( MotionCurve::MC_R_KEY ) * desc.rKeyCount ) == false )
		{
			return false;
		}

		m_RotationKeyList.reserve( desc.rKeyCount );

		for( it = it_begin; it != it_end; ++it )
		{
			const MotionCurve::MC_R_KEY* pSrc = &( *it );
			Mix::Tool::Win32::Graphics::ROTATION_KEY dst;

			dst.time = pSrc->time;
			dst.value.x = pSrc->value[0];
			dst.value.y = pSrc->value[1];
			dst.value.z = pSrc->value[2];
			dst.value.w = pSrc->value[3];

			m_RotationKeyList.push_back( dst );
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// トランスレーションキーリスト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	{
		std::vector<MotionCurve::MC_T_KEY> readList;
		std::vector<MotionCurve::MC_T_KEY>::iterator it_begin;
		std::vector<MotionCurve::MC_T_KEY>::iterator it_end;
		std::vector<MotionCurve::MC_T_KEY>::iterator it;

		readList.resize( desc.tKeyCount );
		it_begin = readList.begin();
		it_end = readList.end();

		if( input.Read( &( readList[0] ), sizeof( MotionCurve::MC_T_KEY ) * desc.tKeyCount ) == false )
		{
			return false;
		}

		m_TranslationKeyList.reserve( desc.tKeyCount );

		for( it = it_begin; it != it_end; ++it )
		{
			const MotionCurve::MC_T_KEY* pSrc = &( *it );
			Mix::Tool::Win32::Graphics::TRANSLATION_KEY dst;

			dst.time = pSrc->time;
			dst.value.x = pSrc->value[0];
			dst.value.y = pSrc->value[1];
			dst.value.z = pSrc->value[2];

			m_TranslationKeyList.push_back( dst );
		}
	}

	return true;
}
*/
bool MotionCurve::Write(	Mix::Tool::Win32::File::OutputStream& output,
							unsigned int rtFlags,
							MOTION_RT_HORIZONAL rtHoriz,
							MOTION_RT_VERTICAL rtVert,
							const D3DXQUATERNION& defR,
							const D3DXVECTOR3& defT )
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ヘッダ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	{
		MotionCurve::MC_DESC desc;

		::wcscpy_s( desc.linkNodeName, sizeof( desc.linkNodeName ) >> 1, m_LinkNodeName.c_str() );

		desc.sKeyCount = m_ScalingKeyList.size();

		if( MIX_TEST_BIT( rtFlags, MOTION_RT_ROTATION ) == 0 )
		{
			desc.rKeyCount = m_RotationKeyList.size();
		}
		else
		{
			desc.rKeyCount = ( m_RotationKeyList.size() > 0 )? 1 : 0;
		}

		if( MIX_TEST_BIT( rtFlags, MOTION_RT_TRANSLATION ) == 0 )
		{
			desc.tKeyCount = m_TranslationKeyList.size();
		}
		else
		{
			if( MIX_TEST_BIT( rtFlags, MOTION_RT_TRANSLATION ) == MOTION_RT_TRANSLATION )
			{
				desc.tKeyCount = ( m_TranslationKeyList.size() > 0 )? 1 : 0;
			}
			else
			{
				desc.tKeyCount = m_TranslationKeyList.size();
			}
		}

		desc.reserve = 0;

		if( output.Write( &desc, sizeof( desc ) ) == false )
		{
			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// スケーリングキーリスト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( m_ScalingKeyList.size() > 0 )
	{
		unsigned int writeSize = sizeof( MotionCurve::MC_S_KEY ) * m_ScalingKeyList.size();
		std::vector<MotionCurve::MC_S_KEY> keyList;

		keyList.reserve( m_ScalingKeyList.size() );

		for( Mix::Tool::Win32::Graphics::VectorKeyList::iterator it = m_ScalingKeyList.begin(); it != m_ScalingKeyList.end(); ++it )
		{
			const Mix::Tool::Win32::Graphics::VECTOR_KEY& srcKey = ( *it );
			keyList.push_back( MC_S_KEY( srcKey ) );
		}

		if( output.Write( &( keyList[0] ), writeSize ) == false )
		{
			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ローテーションキーリスト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( m_RotationKeyList.size() > 0 )
	{
		unsigned int writeSize;
		std::vector<MotionCurve::MC_R_KEY> keyList;

		if( MIX_TEST_BIT( rtFlags, MOTION_RT_ROTATION ) == 0 )
		{
			Mix::Tool::Win32::Graphics::QuaternionKeyList::iterator it_begin = m_RotationKeyList.begin();
			Mix::Tool::Win32::Graphics::QuaternionKeyList::iterator it_end = m_RotationKeyList.end();
			Mix::Tool::Win32::Graphics::QuaternionKeyList::iterator it;

			writeSize = sizeof( MotionCurve::MC_R_KEY ) * m_RotationKeyList.size();
			keyList.reserve( m_RotationKeyList.size() );

			for( it = it_begin; it != it_end; ++it )
			{
				const Mix::Tool::Win32::Graphics::QUATERNION_KEY& srcKey = ( *it );
				keyList.push_back( MC_R_KEY( srcKey ) );
			}
		}
		else
		{
			writeSize = sizeof( MotionCurve::MC_R_KEY );
			keyList.push_back( MC_R_KEY( m_RotationKeyList[0].time, defR ) );
		}

		if( output.Write( &( keyList[0] ), writeSize ) == false )
		{
			return false;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// トランスレーションキーリスト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( m_TranslationKeyList.size() > 0 )
	{
		unsigned int writeSize;
		std::vector<MotionCurve::MC_T_KEY> keyList;

		if( MIX_TEST_BIT( rtFlags, MOTION_RT_TRANSLATION ) == 0 )
		{
			Mix::Tool::Win32::Graphics::VectorKeyList::iterator it_begin = m_TranslationKeyList.begin();
			Mix::Tool::Win32::Graphics::VectorKeyList::iterator it_end = m_TranslationKeyList.end();
			Mix::Tool::Win32::Graphics::VectorKeyList::iterator it;

			writeSize = sizeof( MotionCurve::MC_T_KEY ) * m_TranslationKeyList.size();
			keyList.reserve( m_TranslationKeyList.size() );

			for( it = it_begin; it != it_end; ++it )
			{
				keyList.push_back( MC_T_KEY( ( *it ) ) );
			}
		}
		else
		{
			if( MIX_TEST_BIT( rtFlags, MOTION_RT_TRANSLATION ) == MOTION_RT_TRANSLATION )
			{
				writeSize = sizeof( MotionCurve::MC_T_KEY );
				keyList.push_back( MC_T_KEY( m_TranslationKeyList[0].time, defT ) );
			}
			else if( MIX_TEST_BIT( rtFlags, MOTION_RT_TRANSLATION ) == MOTION_RT_TRANSLATION_XZ )
			{
				Mix::Tool::Win32::Graphics::VectorKeyList::iterator it_begin = m_TranslationKeyList.begin();
				Mix::Tool::Win32::Graphics::VectorKeyList::iterator it_end = m_TranslationKeyList.end();
				Mix::Tool::Win32::Graphics::VectorKeyList::iterator it;

				writeSize = sizeof( MotionCurve::MC_T_KEY ) * m_TranslationKeyList.size();
				keyList.reserve( m_TranslationKeyList.size() );

				switch( rtHoriz )
				{
				case MOTION_RT_H_XY:
					for( it = it_begin; it != it_end; ++it )
					{
						const Mix::Tool::Win32::Graphics::VECTOR_KEY& srcKey = ( *it );
						keyList.push_back( MC_T_KEY( srcKey.time, defT.x, defT.y, srcKey.value.z ) );
					}
					break;

				case MOTION_RT_H_XZ:
					for( it = it_begin; it != it_end; ++it )
					{
						const Mix::Tool::Win32::Graphics::VECTOR_KEY& srcKey = ( *it );
						keyList.push_back( MC_T_KEY( srcKey.time, defT.x, srcKey.value.y, defT.z ) );
					}
					break;

				case MOTION_RT_H_YZ:
					for( it = it_begin; it != it_end; ++it )
					{
						const Mix::Tool::Win32::Graphics::VECTOR_KEY& srcKey = ( *it );
						keyList.push_back( MC_T_KEY( srcKey.time, srcKey.value.x, defT.y, defT.z ) );
					}
					break;
				}
			}
			else if( MIX_TEST_BIT( rtFlags, MOTION_RT_TRANSLATION ) == MOTION_RT_TRANSLATION_Y )
			{
				Mix::Tool::Win32::Graphics::VectorKeyList::iterator it_begin = m_TranslationKeyList.begin();
				Mix::Tool::Win32::Graphics::VectorKeyList::iterator it_end = m_TranslationKeyList.end();
				Mix::Tool::Win32::Graphics::VectorKeyList::iterator it;

				writeSize = sizeof( MotionCurve::MC_T_KEY ) * m_TranslationKeyList.size();
				keyList.reserve( m_TranslationKeyList.size() );

				switch( rtVert )
				{
				case MOTION_RT_V_X:
					for( it = it_begin; it != it_end; ++it )
					{
						const Mix::Tool::Win32::Graphics::VECTOR_KEY& srcKey = ( *it );
						keyList.push_back( MC_T_KEY( srcKey.time, defT.x, srcKey.value.y, srcKey.value.z ) );
					}
					break;

				case MOTION_RT_V_Y:
					for( it = it_begin; it != it_end; ++it )
					{
						const Mix::Tool::Win32::Graphics::VECTOR_KEY& srcKey = ( *it );
						keyList.push_back( MC_T_KEY( srcKey.time, srcKey.value.x, defT.y, srcKey.value.z ) );
					}
					break;

				case MOTION_RT_V_Z:
					for( it = it_begin; it != it_end; ++it )
					{
						const Mix::Tool::Win32::Graphics::VECTOR_KEY& srcKey = ( *it );
						keyList.push_back( MC_T_KEY( srcKey.time, srcKey.value.x, srcKey.value.y, defT.z ) );
					}
					break;
				}
			}
		}

		if( output.Write( &( keyList[0] ), writeSize ) == false )
		{
			return false;
		}
	}

	return true;
}

}}}}
