/// <summary>
        /// Queries dictionary using scopes in order of confidence until it gets any translation pair. Order of scopes: <see cref="apertiumDictQueryScope.exact"/>, <see cref="apertiumDictQueryScope.startingWith"/>, <see cref="apertiumDictQueryScope.anywhere"/>
        /// </summary>
        /// <param name="token">The token to translate, in language of the <c>side</c> specified</param>
        /// <param name="side">Side of the dictionary that the search <c>token</c> is from</param>
        ///<param name="includeAnywhere">if set to <c>true</c> it includes <see cref="apertiumDictQueryScope.anywhere"/> scope </param>
        /// <returns></returns>
        public apertiumDictionaryResult queryBestScope(String token, apertiumDictNeedleSide side = apertiumDictNeedleSide.native, Boolean includeAnywhere = true)
        {
            var result = query(token, apertiumDictQueryScope.exact, side);

            if (!result.Any())
            {
                result = query(token, apertiumDictQueryScope.startingWith, side);
            }

            if (!result.Any() && includeAnywhere)
            {
                result = query(token, apertiumDictQueryScope.anywhere, side);
            }

            return(result);
        }
        /// <summary>
        /// Makes the query.
        /// </summary>
        /// <param name="token">The token.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="side">The side.</param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException">
        /// </exception>
        internal String makeQuery(String token, apertiumDictQueryScope scope = apertiumDictQueryScope.startingWith, apertiumDictNeedleSide side = apertiumDictNeedleSide.native)
        {
            String query = "";

            switch (scope)
            {
            case apertiumDictQueryScope.anywhere:
                query = String.Format(FORMAT_ANYWHERE, token);
                break;

            case apertiumDictQueryScope.exact:
                if (side == apertiumDictNeedleSide.native)
                {
                    query = String.Format(FORMAT_EXACT_SRB, token);
                }
                else if (side == apertiumDictNeedleSide.translated)
                {
                    query = String.Format(FORMAT_EXACT_ENG, token);
                }
                else
                {
                    throw new NotImplementedException();
                }
                break;

            case apertiumDictQueryScope.startingWith:
                if (side == apertiumDictNeedleSide.native)
                {
                    query = String.Format(FORMAT_START_SRB, token);
                }
                else if (side == apertiumDictNeedleSide.translated)
                {
                    query = String.Format(FORMAT_START_ENG, token);
                }
                else
                {
                    throw new NotImplementedException();
                }
                break;
            }
            return(query);
        }
        /// <summary>
        /// Queries for graph for multiple tokens
        /// </summary>
        /// <param name="tokens">The tokens.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="side">The side.</param>
        /// <returns></returns>
        public tokenGraphSet queryForGraphSet(IEnumerable <String> tokens, apertiumDictQueryScope scope = apertiumDictQueryScope.startingWith, apertiumDictNeedleSide side = apertiumDictNeedleSide.native)
        {
            tokenGraphSet outset = new tokenGraphSet();

            var queryRes = query(tokens, scope, side);

            tokenGraphNodeType nType = tokenGraphNodeType.word_eng;

            if (side == apertiumDictNeedleSide.translated)
            {
                nType = tokenGraphNodeType.word_srb;
            }

            outset.Add(queryRes, nType);

            return(outset);
        }
        /// <summary>
        /// Queries by graph leaf child nodes and populates grand children
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="side">The side.</param>
        /// <returns></returns>
        public tokenGraphNode queryByGraphNode(tokenGraphNode graph, apertiumDictQueryScope scope = apertiumDictQueryScope.startingWith, apertiumDictNeedleSide side = apertiumDictNeedleSide.native)
        {
            List <tokenGraphNode> nodes  = graph.getAllLeafs().getTyped <tokenGraphNode>();
            List <String>         tokens = nodes.getNames();
            var queryRes = query(tokens, scope, side);

            foreach (tokenGraphNode node in nodes)
            {
                if (side == apertiumDictNeedleSide.native)
                {
                    node.AddKeyMatches(queryRes, tokenGraphNodeType.word_eng);
                }
                else
                {
                    node.AddValueMatches(queryRes, tokenGraphNodeType.word_srb);
                }
            }

            /*
             * tokenGraphNodeType rType = tokenGraphNodeType.word_eng;
             * tokenGraphNodeType qType = tokenGraphNodeType.word_srb;
             *
             * if (graph.type == tokenGraphNodeType.word_query)
             * {
             *  if (side == apertiumDictNeedleSide.english)
             *  {
             *      rType = tokenGraphNodeType.word_srb;
             *      qType = tokenGraphNodeType.word_eng;
             *  }
             * } else if (graph.type == tokenGraphNodeType.word_eng)
             * {
             *  rType = tokenGraphNodeType.word_srb;
             *  qType = tokenGraphNodeType.word_eng;
             * }
             *
             * graph.AddKeyValueChildren(queryRes, qType, rType, true);
             */
            return(graph);
        }
        /// <summary>
        /// Queries for graph.
        /// </summary>
        /// <param name="token">The token.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="side">The side.</param>
        /// <returns></returns>
        public tokenGraph queryForGraph(String token, apertiumDictQueryScope scope = apertiumDictQueryScope.startingWith, apertiumDictNeedleSide side = apertiumDictNeedleSide.native)
        {
            var        queryRes = query(token, scope, side);
            tokenGraph output   = new tokenGraph(token);

            if (side == apertiumDictNeedleSide.native)
            {
                output.AddKeyMatches(queryRes, tokenGraphNodeType.word_eng);
            }
            else
            {
                output.AddKeyMatches(queryRes, tokenGraphNodeType.word_srb);
            }
            return(output);

            //return (tokenGraph)queryForGraph(new string[] { token }, scope, side);
        }
        /// <summary>
        /// Queries the specified tokens.
        /// </summary>
        /// <param name="tokens">The tokens.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="side">The side.</param>
        /// <returns></returns>
        public apertiumDictionaryResult query(IEnumerable <String> tokens, apertiumDictQueryScope scope = apertiumDictQueryScope.startingWith, apertiumDictNeedleSide side = apertiumDictNeedleSide.native)
        {
            apertiumDictionaryResult output    = new apertiumDictionaryResult();
            List <String>            queryList = new List <string>();

            foreach (String tkn in tokens)
            {
                if (!tkn.isNullOrEmpty())
                {
                    queryList.Add(makeQuery(tkn, scope, side));
                }
            }

            var res = dictionaryOperator.Search(queryList, true, RegexOptions.IgnoreCase);

            foreach (String line in res.getLines(true))
            {
                output.addLine(line);
            }

            return(output);
        }
        /// <summary>
        /// Queries the dictionary for translation of <c>token</c>, into opposite <c>side</c>
        /// </summary>
        /// <param name="token">The token to translate, in language of the <c>side</c> specified</param>
        /// <param name="scope">The scope of search, the matching rule</param>
        /// <param name="side">Side of the dictionary that the search <c>token</c> is from</param>
        /// <returns></returns>
        public apertiumDictionaryResult query(String token, apertiumDictQueryScope scope = apertiumDictQueryScope.startingWith, apertiumDictNeedleSide side = apertiumDictNeedleSide.native)
        {
            apertiumDictionaryResult output = new apertiumDictionaryResult();
            String query = makeQuery(token, scope, side);

            fileTextSearchResult res = dictionaryOperator.Search(query, true, 50, RegexOptions.IgnoreCase);

            foreach (var pair in res)
            {
                output.addLine(pair.Value);
            }

            return(output);
        }
        /// <summary>
        /// Queries dictionary using [first with <c>token</c>, if not found, then with alternative tokens] scopes in order of confidence until it gets any translation pair. Order of scopes: <see cref="apertiumDictQueryScope.exact" />, <see cref="apertiumDictQueryScope.startingWith" />, <see cref="apertiumDictQueryScope.anywhere" />
        /// </summary>
        /// <param name="token">The token to translate, in language of the <c>side</c> specified</param>
        /// <param name="alternativeTokens">The alternative tokens, to try with if the <c>token</c> wasn't resolved, in language of the <c>side</c> specified</param>
        /// <param name="side">Side of the dictionary that the search <c>token</c> is from</param>
        /// <param name="includeAnywhere">if set to <c>true</c> it includes <see cref="apertiumDictQueryScope.anywhere"/> scope </param>
        /// <returns></returns>
        public apertiumDictionaryResult queryBestScope(String token, IEnumerable <String> alternativeTokens, apertiumDictNeedleSide side = apertiumDictNeedleSide.native, Boolean includeAnywhere = true)
        {
            var result = query(token, apertiumDictQueryScope.exact, side);

            if (!result.Any())
            {
                result = query(token, apertiumDictQueryScope.startingWith, side);
            }

            if (!result.Any() && includeAnywhere)
            {
                result = query(token, apertiumDictQueryScope.anywhere, side);
            }

            if (result.Any())
            {
                return(result);
            }

            List <String> altTokens = alternativeTokens.ToList();

            altTokens.Sort((x, y) => y.Length.CompareTo(x.Length));

            if (!result.Any())
            {
                foreach (String infl in altTokens)
                {
                    result = query(infl, apertiumDictQueryScope.exact, apertiumDictNeedleSide.native);
                    if (result.Any())
                    {
                        break;
                    }
                }
            }

            if (!result.Any())
            {
                foreach (String infl in altTokens)
                {
                    result = query(infl, apertiumDictQueryScope.startingWith, apertiumDictNeedleSide.native);
                    if (result.Any())
                    {
                        break;
                    }
                }
            }

            if (!result.Any() && includeAnywhere)
            {
                foreach (String infl in altTokens)
                {
                    result = query(infl, apertiumDictQueryScope.anywhere, apertiumDictNeedleSide.native);
                    if (result.Any())
                    {
                        break;
                    }
                }
            }

            return(result);
        }