#===============================================================================
# Copyright 2010 Matt Chaput
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#    http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#===============================================================================

from alfanous.Support.whoosh.analysis import NgramAnalyzer
from alfanous.Support.whoosh.query import *


class SimpleNgramParser(object):
    """A simple parser that only allows searching a single Ngram field. Breaks
    the input text into grams. It can either discard grams containing spaces,
    or compose them as optional clauses to the query.
    """

    __inittypes__ = dict(fieldname=str, minchars=int, maxchars=int,
                         discardspaces=bool, analyzerclass=type)

    def __init__(self, fieldname, minchars, maxchars, discardspaces=False,
                 analyzerclass=NgramAnalyzer):
        """
        :param fieldname: The field to search.
        :param minchars: The minimum gram size the text was indexed with.
        :param maxchars: The maximum gram size the text was indexed with.
        :param discardspaces: If False, grams containing spaces are made into
            optional clauses of the query. If True, grams containing spaces are
            ignored.
        :param analyzerclass: An analyzer class. The default is the standard
            NgramAnalyzer. The parser will instantiate this analyzer with the
            gram size set to the maximum usable size based on the input string.
        """

        self.fieldname = fieldname
        self.minchars = minchars
        self.maxchars = maxchars
        self.discardspaces = discardspaces
        self.analyzerclass = analyzerclass

    def parse(self, input):
        required = []
        optional = []
        gramsize = max(self.minchars, min(self.maxchars, len(input)))
        if gramsize > len(input):
            return NullQuery(input)

        discardspaces = self.discardspaces
        for t in self.analyzerclass(gramsize)(input):
            gram = t.text
            if " " in gram:
                if not discardspaces:
                    optional.append(gram)
            else:
                required.append(gram)

        if required:
            fieldname = self.fieldname
            andquery = And([Term(fieldname, g) for g in required])
            if optional:
                orquery = Or([Term(fieldname, g) for g in optional])
                return AndMaybe([andquery, orquery])
            else:
                return andquery
        else:
            return NullQuery




