/// <summary>
        /// The create.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <param name="link">
        /// The link.
        /// </param>
        /// <returns>
        /// The <see cref="Chain"/>.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// Thrown if link is unacceptable.
        /// </exception>
        public static Chain Create(Chain source, Link link)
        {
            if (link != Link.Start && link != Link.End && link != Link.CycleEnd && link != Link.CycleStart)
            {
                throw new ArgumentException("Unknown link", "link");
            }

            var result = new Chain(source.GetLength());
            Alphabet sourceAlphabet = source.Alphabet;
            var entries = new int[sourceAlphabet.Cardinality];

            var intervals = new int[sourceAlphabet.Cardinality][];

            for (int j = 0; j < sourceAlphabet.Cardinality; j++)
            {
                var intervalsManager = new CongenericIntervalsManager(source.CongenericChain(j));
                intervals[j] = intervalsManager.GetIntervals(link);
            }

            for (int i = 0; i < source.GetLength(); i++)
            {
                var elementIndex = sourceAlphabet.IndexOf(source[i]);
                int entry = entries[elementIndex]++;
                var interval = intervals[elementIndex][entry];
                result.Set(new ValueInt(interval), i);
            }

            return result;
        }
        public ActionResult Index(
            long[] matterIds,
            int[] characteristicTypeLinkIds,
            int? languageId,
            int? translatorId,
            int notationId,
            int length,
            int step,
            bool delta,
            bool fourier,
            bool growingWindow,
            bool autocorrelation)
        {
            return Action(() =>
            {
                var characteristicNames = new string[characteristicTypeLinkIds.Length];
                var partNames = new List<string>[matterIds.Length];
                var starts = new List<int>[matterIds.Length];
                var lengthes = new List<int>[matterIds.Length];
                var chains = new Chain[matterIds.Length];
                var mattersCharacteristics = new object[matterIds.Length];

                var calculators = new List<IFullCalculator>();
                var links = new List<Link>();
                matterIds = matterIds.OrderBy(m => m).ToArray();
                var matters = db.Matter.Where(m => matterIds.Contains(m.Id)).ToDictionary(m => m.Id);

                for (int k = 0; k < matterIds.Length; k++)
                {
                    long matterId = matterIds[k];
                    Nature nature = db.Matter.Single(m => m.Id == matterId).Nature;

                    long sequenceId;
                    switch (nature)
                    {
                        case Nature.Literature:
                            sequenceId = db.LiteratureSequence.Single(l => l.MatterId == matterId
                                                                        && l.NotationId == notationId
                                                                        && l.LanguageId == languageId
                                                                        && l.TranslatorId == translatorId).Id;
                            break;
                        default:
                            var id = notationId;
                            sequenceId = db.CommonSequence.Single(c => c.MatterId == matterId
                                                                    && c.NotationId == id).Id;
                            break;
                    }

                    chains[k] = commonSequenceRepository.ToLibiadaChain(sequenceId);
                }

                foreach (int characteristicTypeLinkId in characteristicTypeLinkIds)
                {
                    string className = characteristicTypeLinkRepository.GetCharacteristicType(characteristicTypeLinkId).ClassName;
                    calculators.Add(CalculatorsFactory.CreateFullCalculator(className));
                    links.Add(characteristicTypeLinkRepository.GetLibiadaLink(characteristicTypeLinkId));
                }

                for (int i = 0; i < chains.Length; i++)
                {
                    CutRule cutRule = growingWindow
                            ? (CutRule)new CutRuleWithFixedStart(chains[i].GetLength(), step)
                            : new SimpleCutRule(chains[i].GetLength(), step, length);

                    CutRuleIterator iter = cutRule.GetIterator();

                    List<Chain> fragments = new List<Chain>();
                    partNames[i] = new List<string>();
                    starts[i] = new List<int>();
                    lengthes[i] = new List<int>();

                    while (iter.Next())
                    {
                        var fragment = new Chain(iter.GetEndPosition() - iter.GetStartPosition());

                        for (int k = 0; iter.GetStartPosition() + k < iter.GetEndPosition(); k++)
                        {
                            fragment.Set(chains[i][iter.GetStartPosition() + k], k);
                        }

                        fragments.Add(fragment);
                        partNames[i].Add(fragment.ToString());
                        starts[i].Add(iter.GetStartPosition());
                        lengthes[i].Add(fragment.GetLength());
                    }

                    var fragmentsData = new FragmentData[fragments.Count];
                    for (int k = 0; k < fragments.Count; k++)
                    {
                        var characteristics = new double[calculators.Count];
                        for (int j = 0; j < calculators.Count; j++)
                        {
                            characteristics[j] = calculators[j].Calculate(fragments[k], links[j]);
                        }

                        fragmentsData[k] = new FragmentData(characteristics, fragments[k].ToString(), starts[i][k], fragments[k].GetLength());
                    }

                    double[][] differenceData = null;
                    double[][] fourierData = null;
                    double[][] autocorrelationData = null;

                    if (delta)
                    {
                        differenceData = CalculateDifference(fragmentsData.Select(f => f.Characteristics).ToArray());
                    }

                    if (fourier)
                    {
                        fourierData = FastFourierTransform.CalculateFastFourierTransform(fragmentsData.Select(f => f.Characteristics).ToArray());
                    }

                    if (autocorrelation)
                    {
                        autocorrelationData = AutoCorrelation.CalculateAutocorrelation(fragmentsData.Select(f => f.Characteristics).ToArray());
                    }

                    mattersCharacteristics[i] = new { matterName = matters[matterIds[i]].Name, fragmentsData, differenceData, fourierData, autocorrelationData };
                }

                for (int l = 0; l < characteristicTypeLinkIds.Length; l++)
                {
                    characteristicNames[l] = characteristicTypeLinkRepository.GetCharacteristicType(characteristicTypeLinkIds[l]).Name;
                }

                var characteristicsList = new SelectListItem[characteristicTypeLinkIds.Length];
                for (int k = 0; k < characteristicTypeLinkIds.Length; k++)
                {
                    characteristicNames[k] = characteristicTypeLinkRepository.GetCharacteristicName(characteristicTypeLinkIds[k], notationId);
                    characteristicsList[k] = new SelectListItem
                    {
                        Value = k.ToString(),
                        Text = characteristicNames[k],
                        Selected = false
                    };
                }

                string notationName = db.Notation.Single(n => n.Id == notationId).Name;

                var result = new Dictionary<string, object>
                {
                    { "characteristics", mattersCharacteristics },
                    { "notationName", notationName },
                    { "starts", starts },
                    { "partNames", partNames },
                    { "lengthes", lengthes },
                    { "characteristicNames", characteristicNames },
                    { "matterIds", matterIds },
                    { "characteristicsList", characteristicsList }
                };

                return new Dictionary<string, object> { { "data", JsonConvert.SerializeObject(result) } };
            });
        }