/// <summary>
        /// Adds the target building information to debug information message.
        /// </summary>
        /// <param name="info">The information.</param>
        /// <param name="targetBuilding">The target building.</param>
        /// <param name="tagSuffix">The tag suffix.</param>
        private static void AddTargetBuildingInfoToDebugInfoMsg(Log.InfoList info, TargetBuildingInfo targetBuilding, string tagSuffix)
        {
            if (targetBuilding != null)
            {
                info.Add("Demand" + tagSuffix, targetBuilding.Demand);
                info.Add("HasProblem" + tagSuffix, targetBuilding.HasProblem);
                info.Add("ProblemSize" + tagSuffix, targetBuilding.ProblemSize);
                info.Add("ProblemValue" + tagSuffix, targetBuilding.ProblemValue);

                info.Add("ProblemWeight" + tagSuffix, targetBuilding.ProblemWeight);
                info.Add("ServiceProblemCount" + tagSuffix, targetBuilding.ServiceProblemCount);
                info.Add("ServiceProblemSize" + tagSuffix, targetBuilding.ServiceProblemSize);
            }
        }
 /// <summary>
 /// Logs building info for debug use.
 /// </summary>
 /// <param name="buildings">The buildings.</param>
 /// <param name="vehicles">The vehicles.</param>
 /// <param name="districtManager">The district manager.</param>
 /// <param name="citizenManager">The citizen manager.</param>
 /// <param name="buildingId">The building identifier.</param>
 /// <param name="serviceBuilding">The service building.</param>
 /// <param name="targetBuilding">The target building.</param>
 /// <param name="buildingStamp">The building stamp.</param>
 private static void DebugListLog(
     Building[] buildings,
     Vehicle[] vehicles,
     DistrictManager districtManager,
     CitizenManager citizenManager,
     ushort buildingId,
     ServiceBuildingInfo serviceBuilding,
     TargetBuildingInfo targetBuilding,
     BuildingStamp buildingStamp)
 {
     if (buildings[buildingId].Info != null && (buildings[buildingId].m_flags & Building.Flags.Created) == Building.Flags.Created)
     {
         Log.InfoList info = DebugInfoMsg(buildings, vehicles, districtManager, citizenManager, buildingId, serviceBuilding, targetBuilding, buildingStamp);
         Log.DevDebug(typeof(BuildingHelper), "DebugListLog", info.ToString());
     }
 }
        /// <summary>
        /// Collects building info for debug use.
        /// </summary>
        /// <param name="buildings">The buildings.</param>
        /// <param name="vehicles">The vehicles.</param>
        /// <param name="districtManager">The district manager.</param>
        /// <param name="citizenManager">The citizen manager.</param>
        /// <param name="buildingId">The building identifier.</param>
        /// <param name="serviceBuilding">The service building.</param>
        /// <param name="targetBuilding">The target building.</param>
        /// <param name="buildingStamp">The building stamp.</param>
        /// <param name="verbose">If set to <c>true</c> include more information.</param>
        /// <returns>The debug information.</returns>
        private static Log.InfoList DebugInfoMsg(
            Building[] buildings,
            Vehicle[] vehicles,
            DistrictManager districtManager,
            CitizenManager citizenManager,
            ushort buildingId,
            ServiceBuildingInfo serviceBuilding,
            TargetBuildingInfo targetBuilding,
            BuildingStamp buildingStamp,
            bool verbose = false)
        {
            Log.InfoList info = new Log.InfoList();

            info.Add("BuildingId", buildingId);

            if (buildingStamp != null)
            {
                info.Add("O", "BuildingStamp");
            }

            if (serviceBuilding != null)
            {
                info.Add("O", "ServiceBuilding");
            }

            if (targetBuilding != null)
            {
                info.Add("O", "TargetBuilding");
            }

            List <KeyValuePair <string, TargetBuildingInfo> >  targetBuildings  = null;
            List <KeyValuePair <string, ServiceBuildingInfo> > serviceBuildings = null;

            if (verbose && Global.Buildings != null)
            {
                //if (serviceBuilding == null)
                //{
                //    serviceBuilding = Global.Buildings.GetServiceBuilding(buildingId);
                //}

                //if (targetBuilding == null)
                //{
                //    targetBuilding = Global.Buildings.GetTargetBuilding(buildingId);
                //}

                targetBuildings  = new List <KeyValuePair <string, TargetBuildingInfo> >();
                serviceBuildings = new List <KeyValuePair <string, ServiceBuildingInfo> >();

                if (serviceBuilding == null)
                {
                    if (Global.Buildings.Garbage.ServiceBuildings != null && Global.Buildings.Garbage.ServiceBuildings.TryGetValue(buildingId, out serviceBuilding))
                    {
                        serviceBuildings.Add(new KeyValuePair <string, ServiceBuildingInfo>("GB", serviceBuilding));
                    }

                    if (Global.Buildings.DeathCare.ServiceBuildings != null && Global.Buildings.DeathCare.ServiceBuildings.TryGetValue(buildingId, out serviceBuilding))
                    {
                        serviceBuildings.Add(new KeyValuePair <string, ServiceBuildingInfo>("DCB", serviceBuilding));
                    }

                    if (Global.Buildings.HealthCare.ServiceBuildings != null && Global.Buildings.HealthCare.ServiceBuildings.TryGetValue(buildingId, out serviceBuilding))
                    {
                        serviceBuildings.Add(new KeyValuePair <string, ServiceBuildingInfo>("HCB", serviceBuilding));
                    }

                    serviceBuilding = null;
                }

                if (targetBuilding == null)
                {
                    if (Global.Buildings.DeathCare.TargetBuildings != null && Global.Buildings.DeathCare.TargetBuildings.TryGetValue(buildingId, out targetBuilding))
                    {
                        targetBuildings.Add(new KeyValuePair <string, TargetBuildingInfo>("DPB", targetBuilding));
                    }

                    if (Global.Buildings.Garbage.TargetBuildings != null && Global.Buildings.Garbage.TargetBuildings.TryGetValue(buildingId, out targetBuilding))
                    {
                        targetBuildings.Add(new KeyValuePair <string, TargetBuildingInfo>("DB", targetBuilding));
                    }

                    if (Global.Buildings.HealthCare.TargetBuildings != null && Global.Buildings.HealthCare.TargetBuildings.TryGetValue(buildingId, out targetBuilding))
                    {
                        targetBuildings.Add(new KeyValuePair <string, TargetBuildingInfo>("SPB", targetBuilding));
                    }

                    targetBuilding = null;
                }
            }

            try
            {
                info.Add("AI", buildings[buildingId].Info.m_buildingAI.GetType());
                info.Add("InfoName", buildings[buildingId].Info.name);

                string name = GetBuildingName(buildingId);
                if (!String.IsNullOrEmpty(name) && name != buildings[buildingId].Info.name)
                {
                    info.Add("BuildingName", name);
                }
            }
            catch
            {
                info.Add("Error", "Info");
            }

            try
            {
                byte district = districtManager.GetDistrict(buildings[buildingId].m_position);
                info.Add("District", district);
                info.Add("DistrictName", districtManager.GetDistrictName(district));
            }
            catch (Exception ex)
            {
                info.Add("Exception", "District", ex.GetType().ToString(), ex.Message);
            }

            if (buildingStamp != null)
            {
                info.Add("Source", buildingStamp.Source);
                info.Add("SimulationTimeStamp", buildingStamp.SimulationTimeStamp);
                info.Add("SimulationTimeDelta", buildingStamp.SimulationTimeDelta);
            }

            AddServiceBuildingInfoToDebugInfoMsg(info, buildings, serviceBuilding, "B");
            if (serviceBuildings != null)
            {
                foreach (KeyValuePair <string, ServiceBuildingInfo> building in serviceBuildings)
                {
                    AddServiceBuildingInfoToDebugInfoMsg(info, buildings, building.Value, building.Key);
                }
            }

            AddTargetBuildingInfoToDebugInfoMsg(info, targetBuilding, "B");
            if (targetBuildings != null)
            {
                foreach (KeyValuePair <string, TargetBuildingInfo> building in targetBuildings)
                {
                    AddTargetBuildingInfoToDebugInfoMsg(info, building.Value, building.Key);
                }
            }

            if (verbose && Global.Buildings != null)
            {
                info.Add("Categories", Global.Buildings.GetCategories(buildingId));
            }

            float radius = float.NaN;

            int materialMax         = 0;
            int materialAmount      = 0;
            int serviceVehicleCount = 0;

            try
            {
                if (GetCapacityAmount(buildingId, ref buildings[buildingId], out materialAmount, out materialMax, out serviceVehicleCount))
                {
                    info.Add("CapacityAmount", materialAmount);
                    info.Add("CapacityMax", materialMax);
                    info.Add("ServiceVehicleCount", serviceVehicleCount);
                }

                serviceVehicleCount = 0;

                if (buildings[buildingId].Info.m_buildingAI is CemeteryAI)
                {
                    radius = ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_deathCareRadius;

                    info.Add("DeathCareRadius", ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_deathCareRadius);
                    info.Add("CorpseCapacity", ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_corpseCapacity);
                    info.Add("GraveCount", ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_graveCount);
                    info.Add("CustomBuffer1", buildings[buildingId].m_customBuffer1);                                                                                    // GraveUsed?
                    info.Add("CustomBuffer2", buildings[buildingId].m_customBuffer2);
                    info.Add("PR_HC_Calc", ((buildings[buildingId].m_productionRate * ((CemeteryAI)buildings[buildingId].Info.m_buildingAI).m_hearseCount) + 99) / 100); // Hearse capacity?
                    info.Add("IsFull", buildings[buildingId].Info.m_buildingAI.IsFull(buildingId, ref buildings[buildingId]));

                    buildings[buildingId].Info.m_buildingAI.GetMaterialAmount(buildingId, ref buildings[buildingId], TransferManager.TransferReason.Dead, out materialAmount, out materialMax);
                }
                else if (buildings[buildingId].Info.m_buildingAI is LandfillSiteAI)
                {
                    radius = ((LandfillSiteAI)buildings[buildingId].Info.m_buildingAI).m_collectRadius;

                    info.Add("CollectRadius", ((LandfillSiteAI)buildings[buildingId].Info.m_buildingAI).m_collectRadius);
                    info.Add("GarbageAmount", ((LandfillSiteAI)buildings[buildingId].Info.m_buildingAI).GetGarbageAmount(buildingId, ref buildings[buildingId]));
                    info.Add("GarbageCapacity", ((LandfillSiteAI)buildings[buildingId].Info.m_buildingAI).m_garbageCapacity);
                    info.Add("GarbageBuffer", buildings[buildingId].m_garbageBuffer);
                    info.Add("CustomBuffer1", buildings[buildingId].m_customBuffer1); // Garbage?
                    info.Add("IsFull", buildings[buildingId].Info.m_buildingAI.IsFull(buildingId, ref buildings[buildingId]));

                    buildings[buildingId].Info.m_buildingAI.GetMaterialAmount(buildingId, ref buildings[buildingId], TransferManager.TransferReason.Garbage, out materialAmount, out materialMax);
                }
                else if (buildings[buildingId].Info.m_buildingAI is HospitalAI)
                {
                    radius = ((HospitalAI)buildings[buildingId].Info.m_buildingAI).m_healthCareRadius;

                    info.Add("HealthCareRadius", ((HospitalAI)buildings[buildingId].Info.m_buildingAI).m_healthCareRadius);
                    info.Add("PatientCapacity", ((HospitalAI)buildings[buildingId].Info.m_buildingAI).m_patientCapacity);
                    info.Add("IsFull", buildings[buildingId].Info.m_buildingAI.IsFull(buildingId, ref buildings[buildingId]));

                    buildings[buildingId].Info.m_buildingAI.GetMaterialAmount(buildingId, ref buildings[buildingId], TransferManager.TransferReason.Sick, out materialAmount, out materialMax);
                }

                info.Add("materialMax", materialMax);
                info.Add("materialAmount", materialAmount);
                info.Add("materialFree", materialMax - materialAmount);
            }
            catch
            {
                info.Add("Error", "Material");
            }

            ushort ownVehicleCount  = 0;
            ushort madeVehicleCount = 0;

            try
            {
                ushort vehicleId = buildings[buildingId].m_ownVehicles;
                while (vehicleId != 0 && ownVehicleCount < ushort.MaxValue)
                {
                    ownVehicleCount++;
                    try
                    {
                        if ((vehicles[vehicleId].m_transferType == (byte)TransferManager.TransferReason.Garbage || vehicles[vehicleId].m_transferType == (byte)TransferManager.TransferReason.Dead) &&
                            vehicles[vehicleId].Info != null &&
                            (vehicles[vehicleId].m_flags & Vehicle.Flags.Created) == Vehicle.Flags.Created &&
                            (vehicles[vehicleId].m_flags & VehicleHelper.VehicleExists) != ~VehicleHelper.VehicleAll)
                        {
                            madeVehicleCount++;
                        }
                    }
                    catch
                    {
                        info.Add("Error", "Vehicle");
                    }

                    vehicleId = vehicles[vehicleId].m_nextOwnVehicle;
                }
                info.Add("OwnVehicles", ownVehicleCount);
                info.Add("MadeVehicles", madeVehicleCount);
            }
            catch
            {
                info.Add("Error", "Vehicles");
            }

            int productionRate = buildings[buildingId].m_productionRate;

            info.Add("VehicleCount", serviceVehicleCount);
            info.Add("ProductionRate", productionRate);
            info.Add("VehicleCountNominal", ((productionRate * serviceVehicleCount) + 99) / 100);

            try
            {
                int budget = Singleton <EconomyManager> .instance.GetBudget(buildings[buildingId].Info.m_buildingAI.m_info.m_class);

                productionRate = PlayerBuildingAI.GetProductionRate(productionRate, budget);
                int productionRate100     = PlayerBuildingAI.GetProductionRate(100, budget);
                int actualVehicleCount    = ((productionRate * serviceVehicleCount) + 99) / 100;
                int actualVehicleCount100 = ((productionRate100 * serviceVehicleCount) + 99) / 100;

                if (!float.IsNaN(radius))
                {
                    info.Add("Radius", radius);
                }

                info.Add("Budget", budget);
                info.Add("ProductionRateActual", productionRate, productionRate100);
                info.Add("VehicleCountActual", actualVehicleCount, actualVehicleCount100);
                info.Add("SpareVehicles", actualVehicleCount - ownVehicleCount, actualVehicleCount100 - ownVehicleCount);

                if (!float.IsNaN(radius))
                {
                    info.Add("ProductionRange", (double)productionRate * (double)radius * 0.00999999977648258);
                }
            }
            catch
            {
                info.Add("Error", "Budget");
            }

            try
            {
                float range = buildings[buildingId].Info.m_buildingAI.GetCurrentRange(buildingId, ref buildings[buildingId]);
                range = range * range * Global.Settings.RangeModifier;
                if (range < Global.Settings.RangeMinimum)
                {
                    info.Add("Range", range, '<', Global.Settings.RangeMinimum);
                }
                else if (range > Global.Settings.RangeMaximum)
                {
                    info.Add("Range", range, '>', Global.Settings.RangeMaximum);
                }
                else
                {
                    info.Add("Range", range, ">=<");
                }
            }
            catch
            {
                info.Add("Error", "Range");
            }

            try
            {
                List <string> needs = new List <string>();

                if (buildings[buildingId].m_garbageBuffer >= Global.Settings.Garbage.MinimumAmountForDispatch)
                {
                    needs.Add("Filthy");
                }
                else if (buildings[buildingId].m_garbageBuffer >= Global.Settings.Garbage.MinimumAmountForPatrol)
                {
                    needs.Add("Dirty");
                }
                else if (buildings[buildingId].m_garbageBuffer > 0)
                {
                    needs.Add("Dusty");
                }

                if (buildings[buildingId].m_deathProblemTimer > 0)
                {
                    needs.Add("Dead");
                }

                if (buildings[buildingId].m_garbageBuffer * Dispatcher.ProblemBufferModifier >= Dispatcher.ProblemLimitForgotten ||
                    buildings[buildingId].m_deathProblemTimer * Dispatcher.ProblemTimerModifier >= Dispatcher.ProblemLimitForgotten)
                {
                    needs.Add("Forgotten");
                }

                info.Add("Needs", needs);
            }
            catch
            {
                info.Add("Error", "Needs");
            }

            info.Add("DeathProblemTimer", buildings[buildingId].m_deathProblemTimer);
            info.Add("HealthProblemTimer", buildings[buildingId].m_healthProblemTimer);
            info.Add("MajorProblemTimer", buildings[buildingId].m_majorProblemTimer);

            try
            {
                int  citizens = 0;
                int  count    = 0;
                uint unitId   = buildings[buildingId].m_citizenUnits;
                while (unitId != 0)
                {
                    CitizenUnit unit = citizenManager.m_units.m_buffer[unitId];

                    try
                    {
                        for (int i = 0; i < 5; i++)
                        {
                            uint citizenId = unit.GetCitizen(i);
                            if (citizenId != 0)
                            {
                                Citizen citizen = citizenManager.m_citizens.m_buffer[citizenId];
                                if (citizen.Dead && citizen.GetBuildingByLocation() == buildingId)
                                {
                                    citizens++;
                                }
                            }
                        }
                    }
                    catch
                    {
                        info.Add("Error", "Citizen");
                    }

                    count++;
                    if (count > (int)ushort.MaxValue * 10)
                    {
                        break;
                    }

                    unitId = unit.m_nextUnit;
                }
                info.Add("DeadCitizens", citizens);
            }
            catch
            {
                info.Add("Error", "Citizens");
            }

            try
            {
                info.Add("GarbageAmount", buildings[buildingId].Info.m_buildingAI.GetGarbageAmount(buildingId, ref buildings[buildingId]));
                info.Add("GarbageBuffer", buildings[buildingId].m_garbageBuffer);
            }
            catch
            {
                info.Add("Error", "Garbage");
            }

            try
            {
                string problems = buildings[buildingId].m_problems.ToString();
                if (problems.IndexOfAny(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }) >= 0)
                {
                    foreach (Notification.Problem problem in Enum.GetValues(typeof(Notification.Problem)))
                    {
                        if (problem != Notification.Problem.None && (buildings[buildingId].m_problems & problem) == problem)
                        {
                            problems += ", " + problem.ToString();
                        }
                    }
                }
                info.Add("Problems", problems);
            }
            catch
            {
                info.Add("Error", "Problems");
            }

            info.Add("FireIntensoty", buildings[buildingId].m_fireIntensity);

            try
            {
                string flags = buildings[buildingId].m_flags.ToString();
                if (flags.IndexOfAny(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }) >= 0)
                {
                    foreach (Building.Flags flag in Enum.GetValues(typeof(Building.Flags)))
                    {
                        if (flag != Building.Flags.None && (buildings[buildingId].m_flags & flag) == flag)
                        {
                            flags += ", " + flag.ToString();
                        }
                    }
                }
                info.Add("Flags", flags);
            }
            catch
            {
                info.Add("Error", "Flags");
            }

            try
            {
                string status = buildings[buildingId].Info.m_buildingAI.GetLocalizedStatus(buildingId, ref buildings[buildingId]);
                if (!String.IsNullOrEmpty(status))
                {
                    info.Add("Status", status);
                }
            }
            catch
            {
                info.Add("Error", "Status");
            }

            try
            {
                info.Add("AI", buildings[buildingId].Info.m_buildingAI.GetType().AssemblyQualifiedName);
            }
            catch
            {
                info.Add("Error", "AI");
            }

            return(info);
        }