##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
#                     Ivan Tyagov <ivan@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

from DocumentTemplate.DT_Var import sql_quote
from SearchKey import SearchKey

class DefaultKey(SearchKey):
  """ DefaultKey key is an ERP5 portal_catalog search key which is used to render
      SQL expression that will try to exactly one value.
      It supports following special operator ['=', '%', '>' , '>=', '<', '<='] in
      addition to main logical operators like ['OR', 'or', 'AND', 'and'].

      Examples for title column:
        * 'foo or bar'  --> "title = 'foo' OR title = 'bar'"
        * 'foo or =bar'  --> "title = 'foo' OR title = 'bar'"
        * '%foo% or bar' --> "title = '%foo%' OR title = 'bar'"
        * 'Organisation Module' -->  "title = 'Organisation Module'"
        * '"Organisation Module"' --> "title = 'Organisation Module'"
        * '="Organisation Module"' --> "title = 'Organisation Module'"
  """

  # default type of sub Queries to be generated out fo a search string
  default_key_type = 'default'

  tokens =  ('OR', 'AND', 'NOT', 'WORDSET', 'WORD',
             'GREATERTHAN', 'GREATERTHANEQUAL',
             'LESSTHAN', 'LESSTHANEQUAL')

  sub_operators = ('GREATERTHAN', 'GREATERTHANEQUAL',
                    'LESSTHAN', 'LESSTHANEQUAL', 'NOT')


  # Note: Order of placing rules (t_WORD for example) is very important
  def t_OR(self, t):
    r'\s+(OR|or)\s+'
    # operator must have leading and trailing ONLY one white space character
    # otherwise it's treated as a WORD
    t.value = 'OR'
    return t

  def t_AND(self, t):
    r'\s+(AND|and)\s+'
    # operator must have leading and trailing ONLY one white space character
    # otherwise it's treated as a WORD
    t.value = 'AND'
    return t

  def t_NOT(self, t):
    r'(\s+(NOT|not)\s+|!=)'
    # operator must have leading and trailing ONLY one white space character
    # otherwise it's treated as a WORD
    t.value = '!='
    return t

  t_GREATERTHANEQUAL = r'>='
  t_LESSTHANEQUAL = r'<='
  t_GREATERTHAN = r'>'
  t_LESSTHAN = r'<'

  def t_WORD(self, t):
    r'([^"\s<>!][\S\n]*|!([^=\s][\S\n]*)?)'
    # newlines are allowed, because variations are delimited by newlines.
    # WORD may contain arbitrary letters and numbers without white space
    # WORD may contain '%' but not at the beginning or end (otherwise it's KEYWORD)
    value = t.value.strip()
    if value[0] == '=':
      value = value[1:]
    t.value = value
    return t

  def t_WORDSET(self, t):
    r'"[^"]*"'
    #r'"[\x7F-\xFF\w\d\s/%][\x7F-\xFF\w\d\s/%]*"'
    # WORDSET is a combination of WORDs separated by white space
    # and starting/ending with "
    value = t.value.replace('"', '').strip()
    t.value = value
    return t

  def quoteSQLString(self, value, format):
    """ Return a quoted string of the value. """
    if isinstance(value, (int, long,)):
      return str(value)
    return "'%s'" % sql_quote(value)


##  def buildSQLExpressionFromSearchString(self, key, value, format, mode, range_value, stat__):
##    """ Tokenize/analyze passed string value and generate SQL query expressions. """
##    where_expressions = []
##    select_expressions = []
##    tokens = self.tokenize(value)
##    operators_mapping_list = self.groupByOperator(tokens)
##
##    # find if any logical operator exists
##    tokens_values = []
##    logical_operator_found = 0
##    for token in tokens:
##      if token.type not in ('WORDSET', 'WORD',):
##        logical_operator_found = 1
##        break
##      tokens_values.append(token.value.replace("'", ""))
##
##    # build expressions
##    if not logical_operator_found:
##      # no logical operator found so we assume that we search for a combination of words
##      where_expressions.append("%s = '%s'" %(key, ' '.join(tokens_values)))
##    else:
##      # in the search string we have explicitly defined an operator
##      for item in operators_mapping_list:
##        row_tokens_values = []
##        tokens = item['tokens']
##        operator = item['operator']
##        operator_value = None
##        if operator is not None:
##          # operator is standalone expression
##          operator_value = operator.value
##          where_expressions.append('%s' %operator_value)
##        if len(tokens):
##          # no it's not a stand alone expression,
##          # determine it from list of tokens
##          operator_value, sub_tokens = self.getOperatorForTokenList(tokens)
##          row_tokens_values = [x.value for x in sub_tokens]
##          where_expressions.append("%s %s '%s'" %(key, operator_value, ' '.join(row_tokens_values)))
##    return where_expressions, select_expressions