static void BrowseNode(ReadOnlyController controller, IReadOnlyIndex index, Stats stats)
        {
            Assert.That(index != null, "ReadOnly #0");
            Assert.That(controller.Contains(index), "ReadOnly #1");
            IReadOnlyNodeState State = controller.IndexToState(index);

            Assert.That(State != null, "ReadOnly #2");
            Assert.That(State.ParentIndex == index, "ReadOnly #4");

            Node Node;

            if (State is IReadOnlyPlaceholderNodeState AsPlaceholderState)
            {
                Node = AsPlaceholderState.Node;
            }
            else if (State is IReadOnlyPatternState AsPatternState)
            {
                Node = AsPatternState.Node;
            }
            else if (State is IReadOnlySourceState AsSourceState)
            {
                Node = AsSourceState.Node;
            }
            else
            {
                Assert.That(State is IReadOnlyOptionalNodeState, "ReadOnly #5");
                IReadOnlyOptionalNodeState AsOptionalState = (IReadOnlyOptionalNodeState)State;
                IReadOnlyOptionalInner     ParentInner     = AsOptionalState.ParentInner;

                //Assert.That(ParentInner.IsAssigned, "ReadOnly #6");

                Node = AsOptionalState.Node;
            }

            stats.NodeCount++;

            Type           ChildNodeType;
            IList <string> PropertyNames = NodeTreeHelper.EnumChildNodeProperties(Node);

            foreach (string PropertyName in PropertyNames)
            {
                if (NodeTreeHelperChild.IsChildNodeProperty(Node, PropertyName, out ChildNodeType))
                {
                    stats.PlaceholderNodeCount++;

                    IReadOnlyPlaceholderInner Inner      = (IReadOnlyPlaceholderInner)State.PropertyToInner(PropertyName);
                    IReadOnlyNodeState        ChildState = Inner.ChildState;
                    IReadOnlyIndex            ChildIndex = ChildState.ParentIndex;
                    BrowseNode(controller, ChildIndex, stats);
                }

                else if (NodeTreeHelperOptional.IsOptionalChildNodeProperty(Node, PropertyName, out ChildNodeType))
                {
                    stats.OptionalNodeCount++;

                    NodeTreeHelperOptional.GetChildNode(Node, PropertyName, out bool IsAssigned, out Node ChildNode);
                    Debug.Assert(ChildNode is not null);
                    //if (IsAssigned)
                    {
                        if (IsAssigned)
                        {
                            stats.AssignedOptionalNodeCount++;
                        }

                        IReadOnlyOptionalInner Inner      = (IReadOnlyOptionalInner)State.PropertyToInner(PropertyName);
                        IReadOnlyNodeState     ChildState = Inner.ChildState;
                        IReadOnlyIndex         ChildIndex = ChildState.ParentIndex;
                        BrowseNode(controller, ChildIndex, stats);
                    }

                    /*else
                     *  stats.NodeCount++;*/
                }

                else if (NodeTreeHelperList.IsNodeListProperty(Node, PropertyName, out ChildNodeType))
                {
                    stats.ListCount++;

                    IReadOnlyListInner Inner = (IReadOnlyListInner)State.PropertyToInner(PropertyName);

                    for (int i = 0; i < Inner.StateList.Count; i++)
                    {
                        stats.PlaceholderNodeCount++;

                        IReadOnlyPlaceholderNodeState ChildState = Inner.StateList[i];
                        IReadOnlyIndex ChildIndex = ChildState.ParentIndex;
                        BrowseNode(controller, ChildIndex, stats);
                    }
                }

                else if (NodeTreeHelperBlockList.IsBlockListProperty(Node, PropertyName, /*out Type ChildInterfaceType,*/ out ChildNodeType))
                {
                    stats.BlockListCount++;

                    IReadOnlyBlockListInner Inner = (IReadOnlyBlockListInner)State.PropertyToInner(PropertyName);

                    for (int BlockIndex = 0; BlockIndex < Inner.BlockStateList.Count; BlockIndex++)
                    {
                        IReadOnlyBlockState BlockState = Inner.BlockStateList[BlockIndex];

                        stats.PlaceholderNodeCount++;
                        BrowseNode(controller, BlockState.PatternIndex, stats);

                        stats.PlaceholderNodeCount++;
                        BrowseNode(controller, BlockState.SourceIndex, stats);

                        for (int i = 0; i < BlockState.StateList.Count; i++)
                        {
                            stats.PlaceholderNodeCount++;

                            IReadOnlyPlaceholderNodeState ChildState = BlockState.StateList[i];
                            IReadOnlyIndex ChildIndex = ChildState.ParentIndex;
                            BrowseNode(controller, ChildIndex, stats);
                        }
                    }
                }

                else
                {
                    Type         NodeType = Type.FromGetType(Node);
                    PropertyInfo Info     = NodeType.GetProperty(PropertyName);

                    if (Info.PropertyType.IsTypeof <Document>())
                    {
                    }
                    else if (Info.PropertyType.IsTypeof <bool>())
                    {
                    }
                    else if (Info.PropertyType.IsEnum)
                    {
                    }
                    else if (Info.PropertyType.IsTypeof <string>())
                    {
                    }
                    else if (Info.PropertyType.IsTypeof <Guid>())
                    {
                    }
                    else
                    {
                        Assert.That(false, $"State Tree unexpected property: {Info.PropertyType.Name}");
                    }
                }
            }
        }