//////////////////////////////////////////////////////////////////////////////
//
// File: AVP_Pickup.cpp
//
// (AJK - 27.08.2008) Created
//
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header.
#include "Entity/PhysicalObject/Pickup/AVP_Pickup.h"

// ASURA
#include "Blueprint/Asura_Blueprint.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Sound/Asura_Sound_Event_Storage.h"
#include "Sound/Asura_Sound_Event_System.h"

// AVP
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Core/AVP_Game_Core.h"
#include "Entity/PhysicalObject/Pickup/AVP_Pickup_Ammo.h"
#include "Entity/PhysicalObject/Pickup/AVP_Pickup_Health.h"
#include "Entity/PhysicalObject/Pickup/AVP_Pickup_Weapon.h"
#include "Entity/PhysicalObject/Pickup/AVP_Pickup_Tool.h"
#include "Entity/PhysicalObject/Pickup/AVP_Pickup_AudioDiary.h"
#include "LoadAndSave/AVP_WeaponData_System.h"

AVP_Pickup::AVP_Pickup(Asura_Hash_ID uBlueprintHash)
: m_fCollectDistance(0.0f)
, m_fCollectDistanceSqrd(0.0f)
, m_uSkinHash(ASURA_HASH_ID_UNSET)
, m_uPickupSound(ASURA_HASH_ID_UNSET)
, m_uBlueprintHash(uBlueprintHash)
, m_uSinglePlayerInventoryItemBlueprintHash(ASURA_HASH_ID_UNSET)
, m_uMultiplayerInventoryItemBlueprintHash(ASURA_HASH_ID_UNSET)
, m_bAutoPickup(false)
, m_bHasShadow(true)
, m_uRestAnim( ASURA_HASH_ID_UNSET )
, m_fInvertMass(1.0f)
, m_eSpecies(AVP_Settings::AVP_SPECIES_UNKNOWN)
{
}

AVP_Pickup*  AVP_Pickup::Create(Asura_Hash_ID uBlueprintHash)
{
	Asura_Blueprint* pxBlueprint     = Asura_Blueprint_System::GetBlueprintByHashID( uAVP_BLUEPRINT_TYPE_PICKUPS, uBlueprintHash);

	if(pxBlueprint)
	{
		Asura_Value xValue;
		if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_TYPE, xValue))
		{
			switch (xValue.GetIntValue())
			{
				case PICKUP_TYPE_WEAPON :
				{
					return new AVP_Pickup_Weapon(uBlueprintHash);
				}
				case PICKUP_TYPE_HEALTH   :
				{
					return new AVP_Pickup_Health(uBlueprintHash);
				}
				case PICKUP_TYPE_AMMO :
				{
					return new AVP_Pickup_Ammo(uBlueprintHash);
				}
				case PICKUP_TYPE_TOOL :
				{
					return new AVP_Pickup_Tool(uBlueprintHash);
				}
				case PICKUP_TYPE_AUDIODIARY :
				{
					return new AVP_Pickup_AudioDiary(uBlueprintHash);
				}
				default :
				{
					Asura_Assert(false, "Invalid Pickup Type from blueprint!");
					return NULL;
				}
			}
		}
		else
		{
			Asura_Assert(false, "no pickup type param from Blueprint? shouldn't be here!");
			return NULL;
		}
	}
	else
	{
		Asura_Assert(false, "pickup blueprint hash is invalid!");
		return NULL;
	}
}

void AVP_Pickup::InitFromBlueprint()
{
	Asura_Value xValue;
	Asura_Blueprint* pxBlueprint     = Asura_Blueprint_System::GetBlueprintByHashID( uAVP_BLUEPRINT_TYPE_PICKUPS, m_uBlueprintHash);

	// Get Collect distance
	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_SINGLEPLAYERINVENTORYITEMBLUEPRINT, xValue))
	{
		m_uSinglePlayerInventoryItemBlueprintHash = xValue.GetHashIDValue();
	}

	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_MULTIPLAYERINVENTORYITEMBLUEPRINT, xValue))
	{
		m_uMultiplayerInventoryItemBlueprintHash = xValue.GetHashIDValue();
	}

	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_PICK_DISTANCE, xValue))
	{
		m_fCollectDistance     = xValue.GetFloatValue();
		m_fCollectDistanceSqrd = m_fCollectDistance * m_fCollectDistance;
	}	
	else
	{
		Asura_Assert(false, "Blueprint doesn't have collect distance parameter!, will never be picked up!");
	}

	// Get Auto Pickup
	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_AUTOPICKUP, xValue))
	{
		m_bAutoPickup = xValue.GetBoolValue();
	}	
	else
	{
		Asura_Assert(false, "Blueprint doesn't have pickup type parameter!, will be of prompted type by defaut!");
	}

	// Get Allegiance
	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_ALLEGIANCE, xValue))
	{
		m_eSpecies = static_cast<AVP_Settings::Species>( xValue.GetIntValue() );
	}	
	else
	{
		Asura_Assert(false, "Blueprint doesn't have Allegiance parameter!, will never be picked up!");
	}

	// Get Has shadow
	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_CASTSHADOW, xValue))
	{
		m_bHasShadow = xValue.GetBoolValue();
	}	
	else
	{
		Asura_Assert(false, "Blueprint doesn't have shadow parameter!, will have shadow by defaut!");
	}

	// Get Mass
	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_MASS, xValue))
	{
		float fMass = xValue.GetFloatValue();
		m_fInvertMass = (fMass == 0.0f) ? 1.0f : ( 1.0f / fMass );
	}	
	else
	{
		Asura_Assert(false, "Blueprint doesn't have collect distance parameter!, will never be picked up!");
	}

	// Get Sound
	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_SOUND, xValue))
	{
		m_uPickupSound = xValue.GetHashIDValue();
	}	

	// Get Rest Anim
	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_REST_ANIM, xValue))
	{
		m_uRestAnim = xValue.GetHashIDValue();
	}	

	// Get skin override if exists
	if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PICKUP_SKIN_OVERRIDE, xValue))
	{
		m_uSkinHash = xValue.GetHashIDValue();
		if(xValue.GetHashIDValue() == ASURA_HASH_ID_UNSET)
		{
			// Not found in SkinOverride, pick Inventory item defined one
			Asura_Hash_ID uInvItemHash = AVP_Settings::IsMultiPlayer() ? m_uMultiplayerInventoryItemBlueprintHash : m_uSinglePlayerInventoryItemBlueprintHash;
			if((pxBlueprint = Asura_Blueprint_System::GetBlueprintByHashID( uAVP_BLUEPRINT_TYPE_INVENTORY_ITEMS, uInvItemHash )) != NULL)
			{
				if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_SKIN, xValue))
				{
					m_uSkinHash = xValue.GetHashIDValue();
					if(xValue.GetHashIDValue() == ASURA_HASH_ID_UNSET)
					{
						Asura_Assert(false, "blueprint Pickup Skin hash is not set yet!");
					}
				}
				else
				{
					Asura_Assert(false, "blueprint inventory item has no skin param.");
				}
			}
			else
			{
				Asura_Assert(false, "This pickup has no skin defined!.");
			}
		}
	}
	else
	{
		Asura_Assert(false, "No blueprint parameter defined for Pickup skin! shouldn't be here!");
	}

	//set the should load flag for this weapon if retail build
#ifndef ASURA_TOOLS
	const bool bMultiplayer = AVP_Settings::IsMultiPlayer();
	AVP_Game_Core::CharacterType eCharType = AVP_Game_Core::CHARACTERTYPE_UNKNOWN;
	switch ( m_eSpecies )
	{
		case AVP_Settings::AVP_SPECIES_ALIEN: eCharType = ( bMultiplayer ? AVP_Game_Core::MULTIPLAYER_ALIEN : AVP_Game_Core::SINGLE_PLAYER_ALIEN ); break;
		case AVP_Settings::AVP_SPECIES_HUMAN: eCharType = ( bMultiplayer ? AVP_Game_Core::MULTIPLAYER_MARINE : AVP_Game_Core::SINGLE_PLAYER_MARINE ); break;
		case AVP_Settings::AVP_SPECIES_PREDATOR: eCharType = ( bMultiplayer ? AVP_Game_Core::MULTIPLAYER_PREDATOR : AVP_Game_Core::SINGLE_PLAYER_PREDATOR ); break;
		default: Asura_Assert( false, "Invalid character type" ); return;
	}
	Asura_Hash_ID uWeaponHash = ( bMultiplayer ? m_uMultiplayerInventoryItemBlueprintHash : m_uSinglePlayerInventoryItemBlueprintHash );
	if ( uWeaponHash != ASURA_HASH_ID_UNSET )
	{
		u_int uWeaponIndex = AVP_WeaponData_System::GetWeaponIndexFromHash( uWeaponHash, eCharType );
		AVP_WeaponData_System::SetShouldLoadWeapon( uWeaponIndex, eCharType );
	}
#endif
}

void AVP_Pickup::PlayPickupSound(const Asura_Vector_3& xPosition) const
{
	const Asura_Sound_Event* pxEvent = Asura_Sound_Event_Storage::FindEvent(m_uPickupSound);
	if(pxEvent)
	{
		Asura_Sound_Event_System::PlayEvent(pxEvent, NULL, &xPosition);
	}	
}