import enum gameuiCharacterCustomizationPart
{
	Head,
	Body,
	Arms,
}

import enum gameuiCharacterCustomizationEditTag
{
	NewGame,
	HairDresser,
	Ripperdoc,
}

import abstract class gameuiCharacterCustomizationInfo extends IScriptable
{
	import const var name : CName;
	import const var localizedName : String;
	import const var hidden : Bool;
	import const var defaultIndex : Int32;
	import const var uiSlot : CName;
	import const var editTags : array< gameuiCharacterCustomizationEditTag >;
}

import struct gameuiIndexedMorphName
{
	import const var morphName : CName;
	import const var localizedName : String;
}

import class gameuiMorphInfo extends gameuiCharacterCustomizationInfo
{
	import const var morphNames : array< gameuiIndexedMorphName >;
}

import struct gameuiIndexedAppearanceDefinition
{
	import const var name : CName;
	import const var localizedName : String;
	import const var color : Color;
	import const var icon : TweakDBID;
}

import class gameuiAppearanceInfo extends gameuiCharacterCustomizationInfo
{
	import const var useThumbnails : Bool;
	import const var definitions : array< gameuiIndexedAppearanceDefinition >;
}

import struct gameuiSwitcherOption
{
	import const var localizedName : String;
}

import class gameuiSwitcherInfo extends gameuiCharacterCustomizationInfo
{
	import const var options : array< gameuiSwitcherOption >;
}

import struct CharacterCustomizationAttribute
{
	import const var type : gamedataStatType;
	import const var value : Uint32;
}

import abstract class CharacterCustomizationOption extends IScriptable
{
	import const var info : gameuiCharacterCustomizationInfo;
	import const var bodyPart : gameuiCharacterCustomizationPart;
	import const var prevIndex : Uint32;
	import const var currIndex : Uint32;
	import const var isActive : Bool;
	import const var isCensored : Bool;
	import const var isEditable : Bool;
}

importonly abstract class gameuiICharacterCustomizationState extends IScriptable
{
	public import function IsBodyGenderMale() : Bool;
	public import function SetIsBodyGenderMale( isMale : Bool );
	public import function IsBrainGenderMale() : Bool;
	public import function SetIsBrainGenderMale( isMale : Bool );
	public import function GetLifePath() : TweakDBID;
	public import function SetLifePath( lifepath : TweakDBID );
	public import function GetAttributePointsAvailable() : Uint32;
	public import function SetAttributePointsAvailable( value : Uint32 );
	public import function GetAttribute( type : gamedataStatType ) : Uint32;
	public import function SetAttribute( type : gamedataStatType, value : Uint32 );
	public import function GetAttributes() : array< CharacterCustomizationAttribute >;
	public import function IsExpansionStandalone() : Bool;
	public import function SetIsExpansionStandalone( isExpansionStandalone : Bool );
	public import function HasOption( groupName : CName, optionName : CName, isFPP : Bool ) : Bool;
	public import function HasTag( tag : CName ) : Bool;
}

import abstract class gameuiICharacterCustomizationSystem extends IGameSystem
{
	public import function IsTransgenderAllowed() : Bool;
	public import function IsNudityAllowed() : Bool;
	public import function InitializeState() : Bool;
	public import function FinalizeState() : Bool;
	public import function ReFinalizeState() : Bool;
	public import function ClearState() : Bool;
	public import function CancelFinalizedStateUpdate() : Bool;
	public import function GetState() : gameuiICharacterCustomizationState;
	public import function GetHeadOptions( optional presetName : CName ) : array< CharacterCustomizationOption >;
	public import function GetBodyOptions( optional presetName : CName ) : array< CharacterCustomizationOption >;
	public import function GetArmsOptions( optional presetName : CName ) : array< CharacterCustomizationOption >;
	public import function InitializeOptionsFromFinalizedState();
	public import function GetUnitedOptions( head : Bool, body : Bool, arms : Bool, optional headPreset : CName, optional bodyPreset : CName, optional armsPreset : CName ) : array< CharacterCustomizationOption >;
	public import function RandomizeOptions( randomizeData : gameuiCharacterRandomizationParametersData );
	public import function SetRandomizationParameters( data : gameuiCharacterRandomizationParametersData );
	public import function GetRandomizationParameters() : gameuiCharacterRandomizationParametersData;
	public import function ApplyEditTag( editTag : gameuiCharacterCustomizationEditTag );
	public import function ApplyUIPreset( presetName : CName );
	public import function ApplyChangeToOption( const option : CharacterCustomizationOption, newValue : Uint32 );
	public import function TriggerVoiceToneSample();
	public import function HasCharacterCustomizationComponent( entity : Entity ) : Bool;

	public function RegisterPuppetPreviewGameController( puppetPreviewGameController : weak< inkCharacterCreationPuppetPreviewGameController > )
	{
		m_puppetPreviewGameController = puppetPreviewGameController;
	}

	public function UnregisterPuppetPreviewGameController()
	{
		m_puppetPreviewGameController = NULL;
	}

	public function GetPuppetPreviewGameController() : weak< inkCharacterCreationPuppetPreviewGameController >
	{
		return m_puppetPreviewGameController;
	}


	private var m_puppetPreviewGameController : weak< inkCharacterCreationPuppetPreviewGameController >;
}

import class gameuiCharacterCustomizationSystem_OnInitializeOptionsListEvent extends Event
{
}

import class gameuiCharacterCustomizationSystem_OnPresetAppliedEvent extends Event
{
}

import class gameuiCharacterCustomizationSystem_OnAppearanceAppliedEvent extends Event
{
}

import class gameuiCharacterCustomizationSystem_OnRandomizeCompleteEvent extends Event
{
}

import struct gameuiSwitchPair
{
	import var prevOption : weak< CharacterCustomizationOption >;
	import var currOption : weak< CharacterCustomizationOption >;
}

import class gameuiCharacterCustomizationSystem_OnAppearanceSwitchedEvent extends Event
{
	import var pairs : array< gameuiSwitchPair >;
}

import class gameuiCharacterCustomizationSystem_OnOptionUpdatedEvent extends Event
{
	import var option : weak< CharacterCustomizationOption >;
}

import class gameuiCharacterCustomizationSystem_OnReFinalizeStateCompleteEvent extends Event
{
}

import class gameuiCharacterCustomizationSystem_OnCancelFinalizedStateUpdateEvent extends Event
{
}

import class BaseCharacterCreationController extends gameuiMenuGameController
{
	protected var m_eventDispatcher : weak< inkMenuEventDispatcher >;
	protected var m_characterCustomizationState : gameuiICharacterCustomizationState;

	protected import function GetCharacterCustomizationSystem() : gameuiICharacterCustomizationSystem;
	protected import function WaitForRunningInstalations() : Bool;
	protected import function RequestCameraChange( slotName : CName, optional delayed : Bool );

	protected editable var m_nextPageHitArea : inkWidgetRef;

	protected event OnInitialize()
	{
		m_characterCustomizationState = GetCharacterCustomizationSystem().GetState();
		RegisterToGlobalInputCallback( 'OnPostOnRelease', this, 'OnButtonRelease' );
		RegisterToCallback( 'OnRelease', this, 'OnRelease' );
		ForceResetCursorType();
	}

	protected event OnUninitialize()
	{
		UnregisterFromGlobalInputCallback( 'OnPostOnRelease', this, 'OnButtonRelease' );
		UnregisterFromCallback( 'OnRelease', this, 'OnRelease' );
	}

	protected event OnSetMenuEventDispatcher( d : weak< inkMenuEventDispatcher > )
	{
		m_eventDispatcher = d;
	}

	protected event OnShowEngagementScreen( evt : ShowEngagementScreen )
	{
		m_eventDispatcher.SpawnEvent( 'OnHandleEngagementScreen', evt );
	}

	protected event OnRelease( e : inkPointerEvent )
	{
		var target : weak< inkWidget >;
		target = e.GetTarget();
		if( e.IsAction( 'click' ) )
		{
			PlaySound( 'Button', 'OnPress' );
			if( target == inkWidgetRef.Get( m_nextPageHitArea ) )
			{
				NextMenu();
			}
		}
	}

	protected event OnButtonRelease( evt : inkPointerEvent )
	{
		if( !( evt.IsHandled() ) )
		{
			if( evt.IsAction( 'back' ) )
			{
				PlaySound( 'Button', 'OnPress' );
				evt.Handle();
				PriorMenu();
			}
			else
			{
				return false;
			}
			evt.Handle();
		}
	}

	protected virtual function PriorMenu()
	{
		m_eventDispatcher.SpawnEvent( 'OnBack' );
	}

	protected virtual function NextMenu()
	{
		m_eventDispatcher.SpawnEvent( 'OnAccept' );
	}

}

