using Content.Shared.Cargo;
using Content.Shared.Cargo.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Materials;
using Content.Shared.Stacks;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.Trading.Systems;
//TODO: All of this should be removed when PricingSystem in the upstream moves to Shared.
public abstract partial class CP14SharedStationEconomySystem
{
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
///
/// Get a rough price for an entityprototype. Does not consider contained entities.
///
public double GetEstimatedPrice(EntityPrototype prototype)
{
var ev = new EstimatedPriceCalculationEvent(prototype);
RaiseLocalEvent(ref ev);
if (ev.Handled)
return ev.Price;
var price = ev.Price;
price += GetMaterialsPrice(prototype);
price += GetSolutionsPrice(prototype);
// Can't use static price with stackprice
var oldPrice = price;
price += GetStackPrice(prototype);
if (oldPrice.Equals(price))
{
price += GetStaticPrice(prototype);
}
// TODO: Proper container support.
return price;
}
private double GetStaticPrice(EntityPrototype prototype)
{
var price = 0.0;
if (prototype.Components.TryGetValue(Factory.GetComponentName(), out var staticProto))
{
var staticPrice = (StaticPriceComponent) staticProto.Component;
price += staticPrice.Price;
}
return price;
}
private double GetMaterialsPrice(EntityPrototype prototype)
{
double price = 0;
//CP14 We take materials into account when calculating the price in any case.
if ((prototype.Components.ContainsKey(Factory.GetComponentName()) || prototype.ID.StartsWith("CP14")) &&
prototype.Components.TryGetValue(Factory.GetComponentName(), out var composition))
{
var compositionComp = (PhysicalCompositionComponent) composition.Component;
var matPrice = GetMaterialPrice(compositionComp);
if (prototype.Components.TryGetValue(Factory.GetComponentName(), out var stackProto))
{
matPrice *= ((StackComponent) stackProto.Component).Count;
}
price += matPrice;
}
return price;
}
private double GetMaterialPrice(PhysicalCompositionComponent component)
{
double price = 0;
foreach (var (id, quantity) in component.MaterialComposition)
{
price += _prototypeManager.Index(id).Price * quantity;
}
return price;
}
private double GetSolutionsPrice(EntityPrototype prototype)
{
var price = 0.0;
if (prototype.Components.TryGetValue(Factory.GetComponentName(), out var solManager))
{
var solComp = (SolutionContainerManagerComponent) solManager.Component;
price += GetSolutionPrice(solComp);
}
return price;
}
private double GetSolutionPrice(SolutionContainerManagerComponent component)
{
var price = 0.0;
foreach (var (_, prototype) in _solutionContainerSystem.EnumerateSolutions(component))
{
foreach (var (reagent, quantity) in prototype.Contents)
{
if (!_prototypeManager.TryIndex(reagent.Prototype, out var reagentProto))
continue;
// TODO check ReagentData for price information?
price += (float) quantity * reagentProto.PricePerUnit;
}
}
return price;
}
private double GetStackPrice(EntityPrototype prototype)
{
var price = 0.0;
if (prototype.Components.TryGetValue(Factory.GetComponentName(), out var stackpriceProto) &&
prototype.Components.TryGetValue(Factory.GetComponentName(), out var stackProto) &&
!prototype.Components.ContainsKey(Factory.GetComponentName()))
{
var stackPrice = (StackPriceComponent) stackpriceProto.Component;
var stack = (StackComponent) stackProto.Component;
price += stack.Count * stackPrice.Price;
}
return price;
}
}