/// <summary>
        /// Recalculates lane arrows based on present lane connections.
        /// </summary>
        /// <param name="laneId">Affected lane</param>
        /// <param name="nodeId">Affected node</param>
        private void RecalculateLaneArrows(uint laneId, ushort nodeId, bool startNode)
        {
#if DEBUG
            bool logLaneConnections = DebugSwitch.LaneConnections.Get();
#else
            const bool logLaneConnections = false;
#endif
            if (logLaneConnections)
            {
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}) called");
            }

            if (!Options.laneConnectorEnabled)
            {
                return;
            }

            if (!Flags.CanHaveLaneArrows(laneId, startNode))
            {
                if (logLaneConnections)
                {
                    Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                               $"lane {laneId}, startNode? {startNode} must not have lane arrows");
                }

                return;
            }

            if (!HasConnections(laneId, startNode))
            {
                if (logLaneConnections)
                {
                    Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                               $"lane {laneId} does not have outgoing connections");
                }

                return;
            }

            if (nodeId == 0)
            {
                if (logLaneConnections)
                {
                    Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                               "invalid node");
                }

                return;
            }

            var        arrows     = LaneArrows.None;
            NetManager netManager = Singleton <NetManager> .instance;
            ushort     segmentId  = netManager.m_lanes.m_buffer[laneId].m_segment;

            if (segmentId == 0)
            {
                if (logLaneConnections)
                {
                    Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                               "invalid segment");
                }

                return;
            }

            if (logLaneConnections)
            {
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                           $"startNode? {startNode}");
            }

            if (!Services.NetService.IsNodeValid(nodeId))
            {
                if (logLaneConnections)
                {
                    Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                               "Node is invalid");
                }

                return;
            }

            IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;
            ExtSegmentEnd         segEnd    = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)];

            Services.NetService.IterateNodeSegments(
                nodeId,
                (ushort otherSegmentId, ref NetSegment otherSeg) => {
                ArrowDirection dir = segEndMan.GetDirection(ref segEnd, otherSegmentId);

                if (logLaneConnections)
                {
                    Log._Debug(
                        $"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                        $"processing connected segment {otherSegmentId}. dir={dir}");
                }

                // check if arrow has already been set for this direction
                switch (dir)
                {
                case ArrowDirection.Turn: {
                    if (Constants.ServiceFactory.SimulationService.TrafficDrivesOnLeft)
                    {
                        if ((arrows & LaneArrows.Right) != LaneArrows.None)
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        if ((arrows & LaneArrows.Left) != LaneArrows.None)
                        {
                            return(true);
                        }
                    }

                    break;
                }

                case ArrowDirection.Forward: {
                    if ((arrows & LaneArrows.Forward) != LaneArrows.None)
                    {
                        return(true);
                    }

                    break;
                }

                case ArrowDirection.Left: {
                    if ((arrows & LaneArrows.Left) != LaneArrows.None)
                    {
                        return(true);
                    }

                    break;
                }

                case ArrowDirection.Right: {
                    if ((arrows & LaneArrows.Right) != LaneArrows.None)
                    {
                        return(true);
                    }

                    break;
                }

                default: {
                    return(true);
                }
                }

                if (logLaneConnections)
                {
                    Log._Debug(
                        $"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                        $"processing connected segment {otherSegmentId}: need to determine arrows");
                }

                bool addArrow  = false;
                uint curLaneId = netManager.m_segments.m_buffer[otherSegmentId].m_lanes;

                while (curLaneId != 0)
                {
                    if (logLaneConnections)
                    {
                        Log._Debug(
                            $"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                            $"processing connected segment {otherSegmentId}: checking lane {curLaneId}");
                    }

                    if (AreLanesConnected(laneId, curLaneId, startNode))
                    {
                        if (logLaneConnections)
                        {
                            Log._Debug(
                                $"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                                $"processing connected segment {otherSegmentId}: checking lane " +
                                $"{curLaneId}: lanes are connected");
                        }

                        addArrow = true;
                        break;
                    }

                    curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane;
                }

                if (logLaneConnections)
                {
                    Log._Debug(
                        $"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                        $"processing connected segment {otherSegmentId}: finished processing " +
                        $"lanes. addArrow={addArrow} arrows (before)={arrows}");
                }

                if (!addArrow)
                {
                    return(true);
                }

                switch (dir)
                {
                case ArrowDirection.Turn: {
                    if (Constants.ServiceFactory.SimulationService.TrafficDrivesOnLeft)
                    {
                        arrows |= LaneArrows.Right;
                    }
                    else
                    {
                        arrows |= LaneArrows.Left;
                    }

                    break;
                }

                case ArrowDirection.Forward: {
                    arrows |= LaneArrows.Forward;
                    break;
                }

                case ArrowDirection.Left: {
                    arrows |= LaneArrows.Left;
                    break;
                }

                case ArrowDirection.Right: {
                    arrows |= LaneArrows.Right;
                    break;
                }

                default: {
                    return(true);
                }
                }

                if (logLaneConnections)
                {
                    Log._Debug(
                        $"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                        $"processing connected segment {otherSegmentId}: arrows={arrows}");
                }

                return(true);
            });

            if (logLaneConnections)
            {
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): " +
                           $"setting lane arrows to {arrows}");
            }

            LaneArrowManager.Instance.SetLaneArrows(laneId, arrows, true);
        }