/// <summary>
        /// Reorganizes <see cref="AbstractChain"/> into <see cref="AbstractChain"/>.
        /// </summary>
        /// <param name="source">
        /// Source chain.
        /// </param>
        /// <returns>
        /// The <see cref="AbstractChain"/>.
        /// </returns>
        public override AbstractChain Reorganize(AbstractChain source)
        {
            var result = new BaseChain();
            result.ClearAndSetNewLength(source.GetLength() / blockSize);
            IteratorBase iteratorFrom;
            IWritableIterator iteratorTo;

            if (link != Link.End)
            {
                iteratorFrom = new IteratorStart(source, blockSize, blockSize);
                iteratorTo = new IteratorWritableStart(result);
            }
            else
            {
                iteratorFrom = new IteratorEnd(source, blockSize, blockSize);
                iteratorTo = new IteratorWritableEnd(result);
            }

            while (iteratorTo.Next() && iteratorFrom.Next())
            {
                iteratorTo.WriteValue(iteratorFrom.Current());
            }

            return result;
        }
        public IChainGroup <TRequest> AddChainGroupLink(AbstractChain <TRequest> nextChain)
        {
            if (_chainList.Any())
            {
                _chainList.Last().LinkToChain(nextChain);
            }

            _chainList.Add(nextChain);

            return(this);
        }
        /// <summary>
        /// The cut common.
        /// </summary>
        /// <param name="chain">
        /// Source sequence.
        /// </param>
        /// <returns>
        /// <see cref="double"/>.
        /// </returns>
        private double CutCommon(AbstractChain chain)
        {
            for (int length = 1; length <= chain.GetLength(); length++)
            {
                if (CheckRecoveryAvailable(chain, length))
                {
                    return length;
                }
            }

            return chain.GetLength();
        }
        /// <summary>
        /// Reorganizes <see cref="AbstractChain"/> into <see cref="AbstractChain"/>.
        /// </summary>
        /// <param name="source">
        /// Source chain.
        /// </param>
        /// <returns>
        /// The <see cref="AbstractChain"/>.
        /// </returns>
        public override AbstractChain Reorganize(AbstractChain source)
        {
            var resent = new BaseChain(source.GetLength());
            for (int i = 0; i < source.GetLength(); i++)
            {
                var message = source[i] as ValuePhantom ?? new ValuePhantom { source[i] };

                resent.Set(message, i);
            }

            return resent;
        }
        /// <summary>
        /// The check recovery available.
        /// </summary>
        /// <param name="chain">
        /// Source sequence.
        /// </param>
        /// <param name="length">
        /// Length of L-gram.
        /// </param>
        /// <returns>
        /// true if chain is recoverable form L-grams.
        /// </returns>
        private bool CheckRecoveryAvailable(AbstractChain chain, int length)
        {
            var iterator = new IteratorStart(chain, length, 1);
            var alphabet = new Alphabet();

            while (iterator.Next())
            {
                if (alphabet.Contains(iterator.Current()))
                {
                    return false;
                }

                alphabet.Add(iterator.Current());
            }

            return true;
        }
 public void SetNext(AbstractChain chain) => Next = chain;
        public AbstractChain <TRequest> LinkToChain(AbstractChain <TRequest> nextChain)
        {
            _nextChain = nextChain;

            return(_nextChain);
        }