importonly struct StatViewData
{
	import var type : gamedataStatType;
	import var statName : String;
	import var value : Int32;
	import var diffValue : Int32;
	import var isMaxValue : Bool;
	import var valueF : Float;
	import var diffValueF : Float;
	import var statMinValueF : Float;
	import var statMaxValueF : Float;
	import var canBeCompared : Bool;
	import var isCompared : Bool;
	import var statMinValue : Int32;
	import var statMaxValue : Int32;
}

importonly struct ItemViewData
{
	import var primaryStats : array< StatViewData >;
	import var secondaryStats : array< StatViewData >;
	import var id : ItemID;
	import var itemName : String;
	import var categoryName : String;
	import var description : String;
	import var quality : String;
	import var price : Float;
	import var isBroken : Bool;
	import var comparedQuality : gamedataQuality;
}

class InventoryDataManager
{
	private var m_gameInstance : GameInstance;
	private var m_player : weak< PlayerPuppet >;
	private var m_transactionSystem : weak< TransactionSystem >;
	private var m_equipmentSystem : weak< EquipmentSystem >;
	private var m_statsSystem : weak< StatsSystem >;
	private var m_locMgr : UILocalizationMap;

	public function Initialize( player : PlayerPuppet )
	{
		m_player = player;
		m_gameInstance = m_player.GetGame();
		m_transactionSystem = GameInstance.GetTransactionSystem( m_gameInstance );
		m_statsSystem = GameInstance.GetStatsSystem( m_gameInstance );
		m_equipmentSystem = ( ( EquipmentSystem )( GameInstance.GetScriptableSystemsContainer( m_gameInstance ).Get( 'EquipmentSystem' ) ) );
		m_locMgr = new UILocalizationMap;
		m_locMgr.Init();
	}

	public function GetPlayer() : weak< PlayerPuppet >
	{
		return m_player;
	}

	public function GetLastLootedItems( count : Int32, itemsList : ref< array< weak< gameItemData > > > )
	{
		var maxIdx : Int32;
		var sourceList : array< weak< gameItemData > >;
		var tagsList : array< CName >;
		tagsList.PushBack( 'Weapon' );
		tagsList.PushBack( 'Quest' );
		m_transactionSystem.GetItemListByTags( m_player, tagsList, sourceList );
		maxIdx = Min( sourceList.Size(), count );
		while( itemsList.Size() < maxIdx )
		{
			itemsList.PushBack( sourceList.PopBack() );
		}
	}

	public function GetItemsList( out itemsList : array< weak< gameItemData > > )
	{
		m_transactionSystem.GetItemList( m_player, itemsList );
	}

	public function GetItemsListByTag( tag : CName, out itemsList : array< weak< gameItemData > > )
	{
		m_transactionSystem.GetItemListByTag( m_player, tag, itemsList );
	}

	public function GetEquippedItemIdInArea( equipArea : gamedataEquipmentArea, optional slot : Int32 ) : ItemID
	{
		return m_equipmentSystem.GetItemInEquipSlot( m_player, equipArea, slot );
	}

	public const function GetItemEquipArea( itemId : ItemID ) : gamedataEquipmentArea
	{
		return EquipmentSystem.GetEquipAreaType( itemId );
	}

	public function GetExternalItemData( ownerId : EntityID, externalItemId : ItemID ) : weak< gameItemData >
	{
		var itemData : weak< gameItemData >;
		if( ItemID.IsValid( externalItemId ) )
		{
			itemData = m_transactionSystem.GetItemDataByOwnerEntityId( ownerId, externalItemId );
		}
		return itemData;
	}

	public function GetPlayerItemData( externalItemId : ItemID ) : weak< gameItemData >
	{
		var itemData : weak< gameItemData >;
		if( ItemID.IsValid( externalItemId ) )
		{
			itemData = m_transactionSystem.GetItemData( m_player, externalItemId );
		}
		return itemData;
	}

	public function GetExternalItemStats( ownerId : EntityID, externalItemId : ItemID, optional compareItemId : ItemID ) : ItemViewData
	{
		var itemData : weak< gameItemData >;
		var compareItemData : weak< gameItemData >;
		if( ItemID.IsValid( compareItemId ) )
		{
			compareItemData = m_transactionSystem.GetItemData( m_player, compareItemId );
		}
		itemData = m_transactionSystem.GetItemDataByOwnerEntityId( ownerId, externalItemId );
		return GetItemStatsByData( itemData, compareItemData );
	}

	public function GetPlayerItemStats( itemId : ItemID, optional compareItemId : ItemID ) : ItemViewData
	{
		var itemData : weak< gameItemData >;
		var compareItemData : weak< gameItemData >;
		if( ItemID.IsValid( compareItemId ) )
		{
			compareItemData = m_transactionSystem.GetItemData( m_player, compareItemId );
		}
		itemData = m_transactionSystem.GetItemData( m_player, itemId );
		return GetItemStatsByData( itemData, compareItemData );
	}

	private function QualityEnumToName( qualityStatValue : gamedataQuality ) : String
	{
		switch( qualityStatValue )
		{
			case gamedataQuality.Common:
				return "Common";
			case gamedataQuality.Uncommon:
				return "Uncommon";
			case gamedataQuality.Rare:
				return "Rare";
			case gamedataQuality.Epic:
				return "Epic";
			case gamedataQuality.Legendary:
				return "Legendary";
			default:
				return "Common";
		}
	}

	public const function CanCompareItems( itemId : ItemID, compareItemId : ItemID ) : Bool
	{
		var compareItemType : weak< ItemType_Record >;
		var compareItemRecord : Item_Record;
		var statsMapName : String;
		var stats : UIStatsMap_Record;
		var typesToCompare : array< weak< ItemType_Record > >;
		if( !( ItemID.IsValid( itemId ) ) || !( ItemID.IsValid( compareItemId ) ) )
		{
			return false;
		}
		compareItemRecord = TDB.GetItemRecord( ItemID.GetTDBID( compareItemId ) );
		compareItemType = compareItemRecord.ItemType();
		statsMapName = GetStatsUIMapName( itemId );
		if( !( IsStringValid( statsMapName ) ) )
		{
			return false;
		}
		stats = TDB.GetUIStatsMapRecord( TDBID.Create( statsMapName ) );
		stats.TypesToCompareWith( typesToCompare );
		return typesToCompare.Contains( compareItemType );
	}

	public function GetItemStatsByData( itemData : weak< gameItemData >, optional compareWithData : weak< gameItemData > ) : ItemViewData
	{
		var itemId : ItemID;
		var itemRecord : Item_Record;
		var itemCategoryRecord : weak< ItemCategory_Record >;
		var viewData : ItemViewData;
		var statsMapName : String;
		var quality : gamedataQuality;
		itemId = itemData.GetID();
		itemRecord = TDB.GetItemRecord( ItemID.GetTDBID( itemId ) );
		itemCategoryRecord = itemRecord.ItemCategory();
		viewData.id = itemId;
		viewData.itemName = LocKeyToString( itemRecord.DisplayName() );
		viewData.categoryName = m_locMgr.Localize( itemCategoryRecord.Name() );
		viewData.description = LocKeyToString( itemRecord.LocalizedDescription() );
		if( itemData.HasStatData( gamedataStatType.Quality ) )
		{
			quality = RPGManager.GetItemDataQuality( itemData );
			viewData.quality = QualityEnumToName( quality );
		}
		else
		{
			viewData.quality = itemRecord.Quality().Name();
		}
		statsMapName = GetStatsUIMapName( itemId );
		if( IsStringValid( statsMapName ) )
		{
			GetStatsList( TDBID.Create( statsMapName ), itemData, viewData.primaryStats, viewData.secondaryStats, compareWithData );
		}
		return viewData;
	}

	private const function GetStatsUIMapName( itemData : weak< gameItemData > ) : String
	{
		var statsMapName : String;
		if( itemData )
		{
			statsMapName = GetStatsUIMapName( itemData.GetID() );
		}
		return statsMapName;
	}

	private const function GetStatsUIMapName( itemId : ItemID ) : String
	{
		var statsMapName : String;
		var itemRecord : Item_Record;
		var itemType : weak< ItemType_Record >;
		if( ItemID.IsValid( itemId ) )
		{
			itemRecord = TDB.GetItemRecord( ItemID.GetTDBID( itemId ) );
			if( itemRecord )
			{
				itemType = itemRecord.ItemType();
				statsMapName = "UIMaps." + EnumValueToString( "gamedataItemType", ( ( Int32 )( itemType.Type() ) ) );
			}
		}
		return statsMapName;
	}

	private const function GetStatsList( mapPath : TweakDBID, itemData : weak< gameItemData >, primeStatsList : ref< array< StatViewData > >, secondStatsList : ref< array< StatViewData > >, optional compareWithData : weak< gameItemData > )
	{
		var stats : UIStatsMap_Record;
		var statRecords : array< weak< Stat_Record > >;
		var compareItemType : weak< ItemType_Record >;
		var canCompare : Bool;
		var compareTypeList : array< weak< ItemType_Record > >;
		var compareStatRecords : array< weak< Stat_Record > >;
		stats = TDB.GetUIStatsMapRecord( mapPath );
		canCompare = false;
		if( compareWithData != NULL )
		{
			compareItemType = TDB.GetItemRecord( ItemID.GetTDBID( compareWithData.GetID() ) ).ItemType();
			stats.TypesToCompareWith( compareTypeList );
			canCompare = compareTypeList.Contains( compareItemType );
		}
		stats.StatsToCompare( compareStatRecords );
		stats.PrimaryStats( statRecords );
		FillStatsList( itemData, statRecords, primeStatsList, canCompare, compareStatRecords, compareWithData );
		statRecords.Clear();
		stats.SecondaryStats( statRecords );
		FillStatsList( itemData, statRecords, secondStatsList, canCompare, compareStatRecords, compareWithData );
	}

	private const function FillStatsList( itemData : weak< gameItemData >, const statRecords : ref< array< weak< Stat_Record > > >, statList : ref< array< StatViewData > >, canCompare : Bool, const compareStatRecords : ref< array< weak< Stat_Record > > >, optional compareWithData : weak< gameItemData > )
	{
		var i, count : Int32;
		var currStatRecord : weak< Stat_Record >;
		var currentStatViewData : StatViewData;
		var currentType : gamedataStatType;
		var maxValueIdx, maxValue, compareValue : Int32;
		var compareValueF : Float;
		count = statRecords.Size();
		for( i = 0; i < count; i += 1 )
		{
			currStatRecord = statRecords[ i ];
			currentType = currStatRecord.StatType();
			if( itemData.HasStatData( currentType ) )
			{
				currentStatViewData.type = currentType;
				currentStatViewData.statName = m_locMgr.Localize( EnumValueToName( 'gamedataStatType', ( ( Int64 )( currentType ) ) ) );
				currentStatViewData.value = RoundMath( itemData.GetStatValueByType( currentType ) );
				currentStatViewData.valueF = itemData.GetStatValueByType( currentType );
				if( currentStatViewData.value <= 0 )
				{
					continue;
				}
				currentStatViewData.canBeCompared = compareStatRecords.Contains( currStatRecord );
				currentStatViewData.isCompared = ( canCompare && currentStatViewData.canBeCompared ) && compareWithData.HasStatData( currentType );
				if( currentStatViewData.isCompared )
				{
					compareValue = RoundMath( compareWithData.GetStatValueByType( currentType ) );
					compareValueF = compareWithData.GetStatValueByType( currentType );
					currentStatViewData.diffValue = currentStatViewData.value - compareValue;
					currentStatViewData.diffValueF = currentStatViewData.valueF - compareValueF;
				}
				else
				{
					currentStatViewData.diffValue = 0;
					currentStatViewData.diffValueF = 0.0;
				}
				if( currentStatViewData.value > maxValue )
				{
					maxValue = currentStatViewData.value;
					maxValueIdx = i;
				}
				currentStatViewData.statMaxValue = RoundMath( currStatRecord.Max() );
				currentStatViewData.statMinValue = RoundMath( currStatRecord.Min() );
				currentStatViewData.statMaxValueF = currStatRecord.Max();
				currentStatViewData.statMinValueF = currStatRecord.Min();
				statList.PushBack( currentStatViewData );
			}
		}
		if( statList.Size() > 0 )
		{
			statList[ maxValueIdx ].isMaxValue = true;
		}
	}

	public function GetPlayerStats( statsList : ref< array< StatViewData > > )
	{
		var i, count : Int32;
		var statMap : UIStatsMap_Record;
		var statRecords : array< weak< Stat_Record > >;
		var curRecords : weak< Stat_Record >;
		var playerID : StatsObjectID;
		var curData : StatViewData;
		playerID = m_player.GetEntityID();
		statMap = TDB.GetUIStatsMapRecord( T"UIMaps.Player" );
		statMap.PrimaryStats( statRecords );
		count = statRecords.Size();
		for( i = 0; i < count; i += 1 )
		{
			curRecords = statRecords[ i ];
			if( curRecords )
			{
				curData.type = curRecords.StatType();
				curData.value = RoundMath( m_statsSystem.GetStatValue( playerID, curData.type ) );
				curData.statName = m_locMgr.Localize( EnumValueToName( 'gamedataStatType', ( ( Int64 )( curData.type ) ) ) );
				statsList.PushBack( curData );
			}
		}
	}

}

