/// <summary>
        /// Here we check for neighbouring Buildings and Pipes at `pos` param.
        /// If we find the same Flow Type pipe or a Building (which hasnt been selected yet), then we add them to the list and assign the same GridID.
        /// </summary>
        /// <param name="pos">Position of Cell to scan</param>
        /// <param name="gridId">Grid ID of the current Network</param>
        /// <param name="flowIndex">Type of Air Flow</param>
        /// <param name="network">The Air Flow Network Object</param>
        public void ScanCell(IntVec3 pos, int gridId, int flowIndex, AirFlowNet network)
        {
            for (var i = 0; i < 4; i++)
            {
                //var thingList = (pos + GenAdj.CardinalDirections[i]).GetThingList(map);
                //var buildingList = thingList.OfType<Building>();
                //var buildingList = (pos + GenAdj.CardinalDirections[i]).GetThingList(map).OfType<Building>();

                var list = new List <CompAirFlow>();

                //foreach (var current in buildingList)
                foreach (var current in (pos + GenAdj.CardinalDirections[i]).GetThingList(map).OfType <Building>())
                {
                    //var buildingAirComps = current.GetComps<CompAirFlow>().Where(item => item.FlowType == (AirFlowType)flowIndex || (item.FlowType == AirFlowType.Any && item.GridID == RebuildValue));

                    //foreach (var buildingAirComp in buildingAirComps)
                    foreach (var buildingAirComp in current.GetComps <CompAirFlow>()
                             .Where(item => item.FlowType == (AirFlowType)flowIndex || (item.FlowType == AirFlowType.Any && item.GridID == RebuildValue)))
                    {
                        // var result = ValidateBuildingPriority(buildingAirComp, network);
                        // if(!result)
                        if (!ValidateBuildingPriority(buildingAirComp, network))
                        {
                            continue;
                        }

                        ValidateBuilding(buildingAirComp, network);
                        list.Add(buildingAirComp);
                    }
                }

                if (!list.Any())
                {
                    continue;
                }

                foreach (var compAirFlow in list)
                {
                    if (compAirFlow.GridID != -2)
                    {
                        continue;
                    }

                    //var iterator = compAirFlow.parent.OccupiedRect().GetIterator();
                    //while (!iterator.Done())
                    foreach (var item in compAirFlow.parent.OccupiedRect())
                    {
                        PipeGrid[flowIndex, map.cellIndices.CellToIndex(item)] = gridId;
                    }

                    compAirFlow.GridID = gridId;
                    ParseParentCell(compAirFlow, gridId, flowIndex, network);
                }
            }
        }
        /// <summary>
        /// Validate Building as Climate Control Building
        /// </summary>
        /// <param name="compAirFlow">Building Component</param>
        /// <param name="network">Current Network</param>
        private static void ValidateAsTempControl(CompAirFlow compAirFlow, AirFlowNet network)
        {
            var tempControl = compAirFlow as CompAirFlowTempControl;

            if (tempControl == null)
            {
                return;
            }

            if (!network.TempControls.Contains(tempControl))
            {
                network.TempControls.Add(tempControl);
            }

            tempControl.AirFlowNet = network;
        }
        /// <summary>
        /// Validate Building as Air Flow Producer
        /// </summary>
        /// <param name="compAirFlow">Building Component</param>
        /// <param name="network">Current Network</param>
        private static void ValidateAsProducer(CompAirFlow compAirFlow, AirFlowNet network)
        {
            var producer = compAirFlow as CompAirFlowProducer;

            if (producer == null)
            {
                return;
            }

            if (!network.Producers.Contains(producer))
            {
                network.Producers.Add(producer);
            }

            producer.AirFlowNet = network;
        }
        /// <summary>
        /// Validate as a Air Flow Consumer
        /// </summary>
        /// <param name="compAirFlow">Building Component</param>
        /// <param name="network">Current Network</param>
        private static void ValidateAsConsumer(CompAirFlow compAirFlow, AirFlowNet network)
        {
            var consumer = compAirFlow as CompAirFlowConsumer;

            if (consumer == null)
            {
                return;
            }

            if (!network.Consumers.Contains(consumer))
            {
                network.Consumers.Add(consumer);
            }

            consumer.AirFlowNet = network;
        }
        /// <summary>
        /// Check Building Priority. If the Building is a Consumer, we can check for Priority.
        /// If the Priority is Auto, then we skip the priority check
        /// else we check if the Network air type matches the Priority. If it does match we add it to the network. Else we skip it.
        /// </summary>
        /// <param name="compAirFlow">Building Component</param>
        /// <param name="network">Current Network</param>
        /// <returns>Result if we can add the Building to existing Network</returns>
        private static bool ValidateBuildingPriority(CompAirFlow compAirFlow, AirFlowNet network)
        {
            if (compAirFlow == null)
            {
                return(false);
            }

            var consumer = compAirFlow as CompAirFlowConsumer;

            if (consumer == null)
            {
                return(true);
            }

            var priority = consumer.AirTypePriority;

            if (priority == AirTypePriority.Auto)
            {
                return(true);
            }

            return((int)priority == (int)network.FlowType);
        }
 /// <summary>
 /// Validate a Building. Check if it is a Consumer, Producer or Climate Control. If so, Add it to the network.
 /// </summary>
 /// <param name="compAirFlow">Building Component</param>
 /// <param name="network">Current Network</param>
 private static void ValidateBuilding(CompAirFlow compAirFlow, AirFlowNet network)
 {
     ValidateAsProducer(compAirFlow, network);
     ValidateAsTempControl(compAirFlow, network);
     ValidateAsConsumer(compAirFlow, network);
 }
        /// <summary>
        /// Main rebuild function. We Rebuild all different pipetypes here.
        /// </summary>
        /// <param name="flowIndex">Type of Pipe (Red, Blue, Cyan)</param>
        private void RebuildPipeGrid(int flowIndex)
        {
            var flowType = (AirFlowType)flowIndex;

            var runtimeNets = new List <AirFlowNet>();

            for (var i = 0; i < PipeGrid.GetLength(1); i++)
            {
                PipeGrid[flowIndex, i] = RebuildValue;
            }

            var cachedPipes = CachedPipes.Where((item) => item.FlowType == flowType).ToList();

#if DEBUG
            Debug.Log("--- Start Rebuilding --- For Index: " + flowType);
            PrintPipes(cachedPipes);
#endif

            var listCopy = new List <CompAirFlow>(cachedPipes);

            for (var compAirFlow = listCopy.FirstOrDefault(); compAirFlow != null; compAirFlow = listCopy.FirstOrDefault())
            {
                compAirFlow.GridID = _masterId;

                var network = new AirFlowNet()
                {
                    GridID   = compAirFlow.GridID,
                    FlowType = flowType
                };
                //network.GridID = compAirFlow.GridID;
                //network.FlowType = flowType;
                _masterId++;

                /* -------------------------------------------
                 *
                 * Scan the Position - Get all Buildings - And Assign to Network if Priority Allows
                 *
                 * -------------------------------------------
                 */
                //var thingList = compAirFlow.parent.Position.GetThingList(map);
                //var buildingList = thingList.OfType<Building>();
                //var buildingList = compAirFlow.parent.Position.GetThingList(map).OfType<Building>();
                //foreach (var current in buildingList)
                foreach (var current in compAirFlow.parent.Position.GetThingList(map).OfType <Building>())
                {
                    //var buildingAirComps = current.GetComps<CompAirFlow>().Where(item => item.FlowType == AirFlowType.Any && item.GridID == RebuildValue);

                    //foreach (var buildingAirComp in buildingAirComps)
                    foreach (var buildingAirComp in current.GetComps <CompAirFlow>()
                             .Where(item => item.FlowType == AirFlowType.Any && item.GridID == RebuildValue))
                    {
                        //var result = ValidateBuildingPriority(buildingAirComp, network);
                        //if (!result)
                        if (!ValidateBuildingPriority(buildingAirComp, network))
                        {
                            continue;
                        }

                        ValidateBuilding(buildingAirComp, network);
                        //var itr = buildingAirComp.parent.OccupiedRect().GetIterator();
                        //while (!itr.Done())
                        foreach (var item in buildingAirComp.parent.OccupiedRect())
                        {
                            PipeGrid[flowIndex, map.cellIndices.CellToIndex(item)] = compAirFlow.GridID;
                        }

                        buildingAirComp.GridID = compAirFlow.GridID;
                    }
                }

                /* -------------------------------------------
                 *
                 * Iterate the OccupiedRect of the Original compAirFlow (This is the Pipe)
                 * So, We add the Pipe to the Grid.
                 *
                 * -------------------------------------------
                 */
                //var iterator = compAirFlow.parent.OccupiedRect().GetIterator();
                //while (!iterator.Done())
                foreach (var item in compAirFlow.parent.OccupiedRect())
                {
                    PipeGrid[flowIndex, map.cellIndices.CellToIndex(item)] = compAirFlow.GridID;
                }

                ParseParentCell(compAirFlow, compAirFlow.GridID, flowIndex, network);
                listCopy.RemoveAll(item => item.GridID != RebuildValue);

                network.AirFlowNetTick();
#if DEBUG
                Debug.Log(network.DebugString());
#endif
                runtimeNets.Add(network);
            }

            DirtyPipeFlag[flowIndex] = false;
#if DEBUG
            Debug.Log("--- Done Rebuilding ---");
#endif
            _backupNets.AddRange(runtimeNets);
        }
 /// <summary>
 /// Iterate on all the Occupied cells of a Cell. Here we can each Parent Occupied Rect cell.
 /// </summary>
 /// <param name="compAirFlow">The Object under scan</param>
 /// <param name="gridId">Grid ID of the current Network</param>
 /// <param name="flowIndex">Type of Air Flow</param>
 /// <param name="network">The Air Flow Network Object</param>
 private void ParseParentCell(CompAirFlow compAirFlow, int gridId, int flowIndex, AirFlowNet network)
 {
     foreach (var current in compAirFlow.parent.OccupiedRect().EdgeCells)
     {
         ScanCell(current, gridId, flowIndex, network);
     }
 }