from peewee import Clause, SQL, fn, TextField, Field

def _escape_wildcard(search_query):
  """ Escapes the wildcards found in the given search query so that they are treated as *characters*
      rather than wildcards when passed to a LIKE or ILIKE clause with an ESCAPE '!'.
  """
  search_query = (search_query
                  .replace('!', '!!')
                  .replace('%', '!%')
                  .replace('_', '!_')
                  .replace('[', '!['))
  return search_query


def prefix_search(field, prefix_query):
  """ Returns the wildcard match for searching for the given prefix query. """
  # Escape the known wildcard characters.
  prefix_query = _escape_wildcard(prefix_query)
  return Field.__pow__(field, Clause(prefix_query + '%', SQL("ESCAPE '!'")))


def match_mysql(field, search_query):
  """ Generates a full-text match query using a Match operation, which is needed for MySQL.
  """
  if field.name.find('`') >= 0: # Just to be safe.
    raise Exception("How did field name '%s' end up containing a backtick?" % field.name)

  # Note: There is a known bug in MySQL (https://bugs.mysql.com/bug.php?id=78485) that causes
  # queries of the form `*` to raise a parsing error. If found, simply filter out.
  search_query = search_query.replace('*', '')

  return Clause(fn.MATCH(SQL("`%s`" % field.name)), fn.AGAINST(SQL('%s', search_query)),
                parens=True)


def match_like(field, search_query):
  """ Generates a full-text match query using an ILIKE operation, which is needed for SQLite and
      Postgres.
  """
  escaped_query = _escape_wildcard(search_query)
  clause = Clause('%' + escaped_query + '%', SQL("ESCAPE '!'"))
  return Field.__pow__(field, clause)