public static bool GenerateSegmentNameInternal(ushort segmentID, ref string __result, ref List <ushort> usedQueue, bool removePrefix)
        {
            LogUtils.DoLog($"[START {segmentID}]" + __result);
            if ((NetManager.instance.m_segments.m_buffer[segmentID].m_flags & NetSegment.Flags.CustomName) != 0)
            {
                if (usedQueue.Count == 0)
                {
                    return(true);
                }
                else
                {
                    InstanceID id = default;
                    id.NetSegment = segmentID;
                    __result      = Singleton <InstanceManager> .instance.GetName(id);

                    return(false);
                }
            }
            NetSegment segment    = NetManager.instance.m_segments.m_buffer[segmentID];
            NetInfo    info       = segment.Info;
            PrefabAI   ai         = info.GetAI();
            string     format     = null;
            Randomizer randomizer = new Randomizer(segment.m_nameSeed);
            ushort     district   = (ushort)(DistrictManager.instance.GetDistrict(segment.m_middlePosition) & 0xFF);

            Xml.AdrDistrictConfig districtConfig = AdrController.CurrentConfig.GetConfigForDistrict(district);
            Xml.AdrDistrictConfig cityConfig     = AdrController.CurrentConfig.GetConfigForDistrict(0);

            if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None)
            {
                string filenamePrefix = districtConfig.RoadConfig?.QualifierFile ?? "";
                ;
                if ((filenamePrefix == null || !AdrController.LoadedLocalesRoadPrefix.ContainsKey(filenamePrefix)) && district > 0)
                {
                    filenamePrefix = cityConfig.RoadConfig?.QualifierFile;
                }

                if (filenamePrefix != null && AdrController.LoadedLocalesRoadPrefix.ContainsKey(filenamePrefix))
                {
                    LocaleStruct.RoadPrefixFileIndexer currentPrefixFile = AdrController.LoadedLocalesRoadPrefix[filenamePrefix];
                    format = currentPrefixFile.GetPrefix(ai, info.m_forwardVehicleLaneCount == 0 || info.m_backwardVehicleLaneCount == 0, info.m_forwardVehicleLaneCount == info.m_backwardVehicleLaneCount, info.m_halfWidth * 2, (byte)(info.m_forwardVehicleLaneCount + info.m_backwardVehicleLaneCount), randomizer, segmentID);
                }
                LogUtils.DoLog("selectedPrefix = {0}", format);
                if (format == null)
                {
                    string key         = DefaultPrefix(info, ai);
                    uint   rangeFormat = Locale.Count(key);
                    format = Locale.Get(key, randomizer.Int32(rangeFormat));
                }
            }

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

            if (removePrefix)
            {
                format = Regex.Replace(format, "(?!\\{)(\\w+|\\.)(?!\\})", "");
                if (format.IsNullOrWhiteSpace())
                {
                    return(true);
                }
            }

            string genName             = "";
            string sourceRoad          = "";
            string targetRoad          = "";
            string sourceKm            = "";
            string sourceKmWithDecimal = "";
            string sourceDistrict      = "";
            string targetDistrict      = "";
            string direction           = "";

            if (format.Contains("{0}"))
            {
                GetGeneratedRoadName(segment, ai, district, out genName);
                if (genName == null)
                {
                    return(true);
                }
            }
            ushort sourceSeg = 0;
            ushort targetSeg = 0;

            if (format.Contains("{1}") || format.Contains("{2}") || format.Contains("{3}") || format.Contains("{4}") || format.Contains("{7}"))
            {
                SegmentUtils.GetSegmentRoadEdges(segmentID, true, true, true, out ComparableRoad startRef, out ComparableRoad endRef, out _);

                sourceSeg = startRef.segmentReference;
                targetSeg = endRef.segmentReference;

                if (format.Contains("{1}"))
                {
                    if (!usedQueue.Contains(sourceSeg))
                    {
                        usedQueue.Add(sourceSeg);
                        GenerateSegmentNameInternal(sourceSeg, ref sourceRoad, ref usedQueue, false);
                    }
                }
                if (format.Contains("{2}"))
                {
                    if (!usedQueue.Contains(targetSeg))
                    {
                        usedQueue.Add(targetSeg);
                        GenerateSegmentNameInternal(targetSeg, ref targetRoad, ref usedQueue, false);
                    }
                }
                if (format.Contains("{3}") || format.Contains("{4}"))
                {
                    float km = GetNumberAt(startRef.segmentReference, NetManager.instance.m_segments.m_buffer[startRef.segmentReference].m_startNode == startRef.nodeReference) / 1000f;
                    sourceKm            = km.ToString("0");
                    sourceKmWithDecimal = km.ToString("0.0");
                }
                if (format.Contains("{7}"))//direction
                {
                    int cardinalDirection = SegmentUtils.GetCardinalDirection(startRef, endRef);

                    direction = Locale.Get("K45_CARDINAL_POINT_SHORT", cardinalDirection.ToString());
                }
            }
            if (format.Contains("{5}") || format.Contains("{6}"))
            {
                GetSegmentRoadEdges(segmentID, false, false, false, out ComparableRoad startRef, out ComparableRoad endRef, out _);
                if (format.Contains("{5}"))//source district
                {
                    sourceDistrict = GetDistrictAt(startRef);
                }
                if (format.Contains("{6}"))//target district
                {
                    targetDistrict = GetDistrictAt(endRef);
                }
            }
            if (AddressesMod.DebugMode)
            {
                __result = $"[{segmentID}] " + StringUtils.SafeFormat(format, genName, sourceSeg, targetSeg, sourceKm, sourceKmWithDecimal, sourceDistrict, targetDistrict, direction)?.Trim();
            }
            else
            {
                __result = StringUtils.SafeFormat(format, genName, sourceRoad, targetRoad, sourceKm, sourceKmWithDecimal, sourceDistrict, targetDistrict, direction)?.Trim();
            }
            LogUtils.DoLog($"[END {segmentID}]" + __result);
            return(false);
        }
        public string GetPrefix(PrefabAI ai, bool isOneWay, bool isSymmetric, float width, byte lanes, Randomizer rand, ushort segmentId, ushort seedId)
        {
            Highway  highway = Highway.ANY;
            RoadType type    = RoadType.NONE;

            if (ai is RoadBaseAI baseAi)
            {
                if (baseAi is DamAI)
                {
                    type = RoadType.DAM;
                }
                else if (baseAi is RoadBridgeAI)
                {
                    type = RoadType.BRIDGE;
                }
                else if (baseAi.IsUnderground())
                {
                    type = RoadType.TUNNEL;
                }
                else
                {
                    type = RoadType.GROUND;
                }
                highway = baseAi.m_highwayRules ? Highway.TRUE : Highway.FALSE;
            }
            if (type == RoadType.NONE)
            {
                LogUtils.DoLog($"AI NAO IDENTIFICADA: {ai}");
                return(null);
            }

            OneWay            wayVal            = isOneWay ? OneWay.TRUE : OneWay.FALSE;
            Symmetry          symVal            = isSymmetric ? Symmetry.TRUE : Symmetry.FALSE;
            LinkingType       linking           = LinkingType.NO_LINKING;
            SeedConfiguration seedConfiguration =
                (AdrNameSeedDataXml.Instance.NameSeedConfigs.TryGetValue(seedId, out AdrNameSeedConfig seedConf) && !(seedConf.HighwayParent is null) ? SeedConfiguration.HAS_HIGHWAY_TYPE : SeedConfiguration.NO_HIGHWAY_TYPE)
                | ((seedConf?.ForcedName).IsNullOrWhiteSpace()? SeedConfiguration.NO_FORCED_NAME : SeedConfiguration.HAS_FORCED_NAME);
            bool hasStart = true;
            bool hasEnd   = true;

            if (wayVal == OneWay.TRUE && lanes <= 2)
            {
                SegmentUtils.GetSegmentRoadEdges(segmentId, true, true, true, out ComparableRoad startRef, out ComparableRoad endRef, out _);
                LogUtils.DoLog($"OneWay s={startRef}; e= {endRef}");
                if (startRef.segmentReference == 0 || endRef.segmentReference == 0)
                {
                    hasStart = startRef.segmentReference != 0;
                    hasEnd   = endRef.segmentReference != 0;
                }
                else if ((NetManager.instance.m_segments.m_buffer[startRef.segmentReference].Info.GetAI() is RoadBaseAI baseAiSource && baseAiSource.m_highwayRules) ||
                         (NetManager.instance.m_segments.m_buffer[endRef.segmentReference].Info.GetAI() is RoadBaseAI baseAiTarget && baseAiTarget.m_highwayRules))

                {
                    switch (startRef.CompareTo(endRef))
                    {
                    case 1:
                        linking = LinkingType.FROM_BIG;
                        break;

                    case 0:
                        linking = LinkingType.SAME_SIZE;
                        break;

                    case -1:
                        linking = LinkingType.FROM_SMALL;
                        break;
                    }
                }
            }

            List <RoadPrefixFileItem> filterResult = m_prefixes.Where(x =>
                                                                      (x.roadType & type) == type &&
                                                                      (x.oneWay & wayVal) == wayVal &&
                                                                      (x.symmetry & symVal) == symVal &&
                                                                      (x.highway & highway) == highway &&
                                                                      (wayVal == OneWay.FALSE || ((x.linking & linking) == linking)) &&
                                                                      (hasStart || !x.requireSource) &&
                                                                      (hasEnd || !x.requireTarget) &&
                                                                      x.minWidth <= width + 0.99f &&
                                                                      width + 0.99f < x.maxWidth &&
                                                                      x.minLanes <= lanes &&
                                                                      lanes < x.maxLanes &&
                                                                      (x.seedConfig & seedConfiguration) == seedConfiguration
                                                                      ).ToList();

            if (filterResult.Count == 0 && linking != LinkingType.NO_LINKING)
            {
                filterResult = m_prefixes.Where(x =>
                                                (x.roadType & type) == type &&
                                                (x.oneWay & wayVal) == wayVal &&
                                                (x.symmetry & symVal) == symVal &&
                                                (x.highway & highway) == highway &&
                                                (wayVal == OneWay.FALSE || ((x.linking & LinkingType.NO_LINKING) == LinkingType.NO_LINKING)) &&
                                                (hasStart || !x.requireSource) &&
                                                (hasEnd || !x.requireTarget) &&
                                                x.minWidth <= width + 0.99f &&
                                                width + 0.99f < x.maxWidth &&
                                                x.minLanes <= lanes &&
                                                lanes < x.maxLanes &&
                                                (x.seedConfig & seedConfiguration) == seedConfiguration
                                                ).ToList();
            }
            LogUtils.DoLog($"Results for: {type} O:{wayVal} S:{symVal} H:{highway} W:{width} L:{lanes} Lk:{linking} Hs:{hasStart} He:{hasEnd} Sc:{seedConfiguration} = {filterResult?.Count}");
            if (filterResult?.Count == 0)
            {
                return(null);
            }

            return(filterResult[rand.Int32((uint)(filterResult.Count))].name);
        }