using System;
using System.Collections.Generic;
using System.Linq;
using Content.Server.Atmos;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Interfaces;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Server.NodeContainer.NodeGroups
{
public interface IPipeNet : INodeGroup, IGasMixtureHolder
{
///
/// Causes gas in the PipeNet to react.
///
void Update();
}
[NodeGroup(NodeGroupID.Pipe)]
public class PipeNet : BaseNodeGroup, IPipeNet
{
[ViewVariables] public GasMixture Air { get; set; } = new() {Temperature = Atmospherics.T20C};
[ViewVariables] private readonly List _pipes = new();
[ViewVariables] private AtmosphereSystem? _atmosphereSystem;
public GridId Grid => GridId;
public override void Initialize(Node sourceNode)
{
base.Initialize(sourceNode);
_atmosphereSystem = EntitySystem.Get();
_atmosphereSystem.AddPipeNet(this);
}
public void Update()
{
_atmosphereSystem?.React(Air, this);
}
public override void LoadNodes(List groupNodes)
{
base.LoadNodes(groupNodes);
foreach (var node in groupNodes)
{
var pipeNode = (PipeNode) node;
_pipes.Add(pipeNode);
pipeNode.JoinPipeNet(this);
Air.Volume += pipeNode.Volume;
}
}
public override void RemoveNode(Node node)
{
base.RemoveNode(node);
var pipeNode = (PipeNode) node;
Air.Volume -= pipeNode.Volume;
// TODO: Bad O(n^2)
_pipes.Remove(pipeNode);
}
public override void AfterRemake(IEnumerable> newGroups)
{
RemoveFromGridAtmos();
var buffer = new GasMixture(Air.Volume) {Temperature = Air.Temperature};
var atmosphereSystem = EntitySystem.Get();
foreach (var newGroup in newGroups)
{
if (newGroup.Key is not IPipeNet newPipeNet)
continue;
var newAir = newPipeNet.Air;
var newVolume = newGroup.Cast().Sum(n => n.Volume);
buffer.Clear();
atmosphereSystem.Merge(buffer, Air);
buffer.Multiply(MathF.Min(newVolume / Air.Volume, 1f));
atmosphereSystem.Merge(newAir, buffer);
}
}
private void RemoveFromGridAtmos()
{
DebugTools.AssertNotNull(_atmosphereSystem);
_atmosphereSystem?.RemovePipeNet(this);
}
}
}