class CodexSystem extends ScriptableSystem
{
	private var m_codex : array< SCodexRecord >;
	private var m_blackboard : weak< IBlackboard >;

	private export override function OnAttach()
	{
		m_blackboard = GameInstance.GetBlackboardSystem( GetGameInstance() ).Get( GetAllBlackboardDefs().UI_CodexSystem );
		codexInit();
	}

	private function codexInit()
	{
		var initialRecords : array< weak< CodexRecord_Record > >;
		var codex : Codex_Record;
		var i : Int32;
		codex = TweakDBInterface.GetCodexRecord( T"Codex.PlayerCodex" );
		codex.Entries( initialRecords );
		for( i = 0; i < initialRecords.Size(); i += 1 )
		{
			AddCodexRecord( initialRecords[ i ] );
		}
	}

	public const function IsRecordLocked( recordID : TweakDBID ) : Bool
	{
		var i : Int32;
		for( i = 0; i < m_codex.Size(); i += 1 )
		{
			if( ( m_codex[ i ].RecordID == recordID ) && !( m_codex[ i ].Unlocked ) )
			{
				return true;
			}
		}
		return false;
	}

	public const function GetCodexRecordPartContent( recordID : TweakDBID, partName : CName ) : String
	{
		var content : String;
		var rid : Int32;
		var i : Int32;
		rid = GetCodexRecordIndex( recordID );
		if( rid != -1 )
		{
			for( i = 0; i < m_codex[ rid ].RecordContent.Size(); i += 1 )
			{
				if( m_codex[ rid ].RecordContent[ i ].PartName == partName )
				{
					content = m_codex[ rid ].RecordContent[ i ].PartContent;
				}
			}
		}
		return content;
	}

	public const function IsRecordPartLocked( recordID : TweakDBID, partName : CName ) : Bool
	{
		var i : Int32;
		var j : Int32;
		for( i = 0; i < m_codex.Size(); i += 1 )
		{
			if( m_codex[ i ].RecordID == recordID )
			{
				for( j = 0; j < m_codex[ i ].RecordContent.Size(); j += 1 )
				{
					if( m_codex[ i ].RecordContent[ j ].PartName == partName && !( m_codex[ i ].RecordContent[ j ].Unlocked ) )
					{
						return true;
					}
				}
			}
		}
		return false;
	}

	public const function GetCodex() : array< SCodexRecord >
	{
		return m_codex;
	}

	public const function GetCodexRecordParts( recordTweak : TweakDBID ) : array< SCodexRecordPart >
	{
		var nullRecordContent : array< SCodexRecordPart >;
		var rid : Int32;
		rid = GetCodexRecordIndex( recordTweak );
		if( rid != -1 )
		{
			return m_codex[ rid ].RecordContent;
		}
		return nullRecordContent;
	}

	public const function GetCodexRecordIndex( recordTweak : TweakDBID ) : Int32
	{
		var i : Int32;
		for( i = 0; i < m_codex.Size(); i += 1 )
		{
			if( m_codex[ i ].RecordID == recordTweak )
			{
				return i;
			}
		}
		return -1;
	}

	private function AddCodexRecord( record : CodexRecord_Record )
	{
		var i : Int32;
		var contentRecords : array< weak< CodexRecordPart_Record > >;
		var newCodexEntry : SCodexRecord;
		var newCodexPartEntry : SCodexRecordPart;
		newCodexEntry.RecordID = record.GetID();
		newCodexEntry.Tags = record.Tags();
		record.RecordContent( contentRecords );
		for( i = 0; i < contentRecords.Size(); i += 1 )
		{
			newCodexPartEntry.PartName = contentRecords[ i ].PartName();
			newCodexPartEntry.PartContent = contentRecords[ i ].PartContent();
			newCodexPartEntry.Unlocked = false;
			newCodexEntry.RecordContent.PushBack( newCodexPartEntry );
		}
		if( record.UnlockedFromStart() )
		{
			newCodexEntry.Unlocked = true;
		}
		else
		{
			newCodexEntry.Unlocked = false;
		}
		m_codex.PushBack( newCodexEntry );
	}

	private function UnlockRecord( recordTweak : TweakDBID )
	{
		var rid : Int32;
		rid = GetCodexRecordIndex( recordTweak );
		if( rid != -1 )
		{
			m_codex[ GetCodexRecordIndex( recordTweak ) ].Unlocked = true;
		}
	}

	private function UnlockCodexPart( recordTweak : TweakDBID, partName : CName )
	{
		var rid : Int32;
		var i : Int32;
		rid = GetCodexRecordIndex( recordTweak );
		if( rid != -1 )
		{
			for( i = 0; i < m_codex[ rid ].RecordContent.Size(); i += 1 )
			{
				if( m_codex[ rid ].RecordContent[ i ].PartName == partName )
				{
					m_codex[ rid ].RecordContent[ i ].Unlocked = true;
				}
			}
		}
	}

	private function LockRecord( recordTweak : TweakDBID )
	{
		var rid : Int32;
		rid = GetCodexRecordIndex( recordTweak );
		if( rid != -1 )
		{
			m_codex[ rid ].Unlocked = false;
		}
	}

	private function SendCallback()
	{
		m_blackboard.SetVariant( GetAllBlackboardDefs().UI_CodexSystem.CodexUpdated, true );
		m_blackboard.SignalVariant( GetAllBlackboardDefs().UI_CodexSystem.CodexUpdated );
	}

	private function OnCodexUnlockRecordRequest( request : CodexUnlockRecordRequest )
	{
		UnlockRecord( request.codexRecordID );
		SendCallback();
	}

	private function OnCodexLockRecordRequest( request : CodexLockRecordRequest )
	{
		LockRecord( request.codexRecordID );
		SendCallback();
	}

	private function OnAddCodexRecordRequest( request : CodexAddRecordRequest )
	{
		AddCodexRecord( TweakDBInterface.GetCodexRecordRecord( request.codexRecordID ) );
		SendCallback();
	}

	private function OnUnlockCodexPartRequest( request : UnlockCodexPartRequest )
	{
		UnlockCodexPart( request.codexRecordID, request.partName );
		SendCallback();
	}

}

class CodexLockRecordRequest extends ScriptableSystemRequest
{
	var codexRecordID : TweakDBID;
}

class UnlockCodexPartRequest extends ScriptableSystemRequest
{
	var codexRecordID : TweakDBID;
	var partName : CName;
}

class CodexUnlockRecordRequest extends ScriptableSystemRequest
{
	var codexRecordID : TweakDBID;
}

class CodexAddRecordRequest extends ScriptableSystemRequest
{
	var codexRecordID : TweakDBID;
}

class CodexPrintRecordsRequest extends ScriptableSystemRequest
{
}

struct SCodexRecord
{
	var RecordID : TweakDBID;
	var RecordContent : array< SCodexRecordPart >;
	var Tags : array< CName >;
	var Unlocked : Bool;
}

struct SCodexRecordPart
{
	var PartName : CName;
	var PartContent : String;
	var Unlocked : Bool;
}

