/// <summary>
        /// Initializes a new instance of the <see cref="MenuDisplay{T}"/> class.
        /// </summary>
        /// <param name="point">The point where the menu should be displayed.</param>
        /// <param name="displayedLines">
        /// The maximum number of console lines the menu display should use.
        /// The menu can display more options than this value.
        /// Values greater than the height of the console can result in odd effects.</param>
        public MenuDisplay(IConsole console, ConsolePoint point, int displayedLines)
        {
            _console      = console ?? throw new ArgumentNullException(nameof(console));
            _windowOrigin = _console.GetWindowPosition();
            _origin       = point;
            _options      = new MenuOptionCollection <TOption>();
            _options.CollectionChanged += OptionsCollectionChanged;
            _displayed = new List <ConsoleString>();
            for (int i = 0; i < displayedLines; i++)
            {
                _displayed.Add("");
            }
            _displayOffset = 0;

            _index    = -1;
            _prompt   = "> ";
            _noPrompt = "  ";

            _prefixTop    = new PrefixKeyCollection();
            _prefixBottom = new PrefixKeyCollection();
            _hasPrefix    = false;

            _prefixTop.PrefixSetChanged    += UpdateAllOptions;
            _prefixBottom.PrefixSetChanged += UpdateAllOptions;
        }
        private void OptionsCollectionChanged(MenuOptionCollection <TOption> collection, CollectionUpdateTypes updateType, int index, int count)
        {
            switch (updateType)
            {
            case CollectionUpdateTypes.Clear:
                _displayOffset = 0;
                _index         = -1;
                UpdateAllOptions();
                break;

            case CollectionUpdateTypes.Insert:
            {
                if (index <= SelectedIndex)
                {
                    SelectedIndex += count;
                }

                var from = Math.Max(Math.Min(index, _options.Count - PrefixesBottom.Count - 1), 0);
                for (int i = from; i < _options.Count; i++)
                {
                    UpdateOption(i);
                }
            }
            break;

            case CollectionUpdateTypes.Remove:
            {
                var from = Math.Max(Math.Min(index, _options.Count - PrefixesBottom.Count - 1), 0);

                var newOffset = Math.Max(0, _options.Count - _displayed.Count);
                if (newOffset < _displayOffset)
                {
                    from           = Math.Max(from - _displayOffset + newOffset, 0);
                    _displayOffset = newOffset;
                }

                for (int i = from; i < _options.Count; i++)
                {
                    UpdateOption(i);
                }

                UpdateOption(_options.Count);

                if (index < SelectedIndex || _options.Count == SelectedIndex)
                {
                    SelectedIndex -= count;
                }
            }
            break;

            case CollectionUpdateTypes.Replace:
                if (_index >= index && _index < index + count)
                {
                    _index = -1;
                }

                for (int i = 0; i < count; i++)
                {
                    UpdateOption(i + index);
                }
                break;

            case CollectionUpdateTypes.Update:
                for (int i = 0; i < count; i++)
                {
                    UpdateOption(i + index);
                }
                break;
            }
        }