# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

"""Utility functions and classes for dealing with saved queries.

Saved queries can be part of the project issue config, where they are
called "canned queries".  Or, they can be personal saved queries that
may appear in the search scope drop-down, on the user's dashboard, or
in the user's subscription.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import re

from framework import template_helpers
from tracker import tracker_bizobj
from tracker import tracker_constants


MAX_QUERIES = 100


def ParseSavedQueries(cnxn, post_data, project_service, prefix=''):
  """Parse form data for the Saved Queries part of an admin form."""
  saved_queries = []
  for i in range(1, MAX_QUERIES + 1):
    if ('%ssavedquery_name_%s' % (prefix, i)) not in post_data:
      continue  # skip any entries that are blank or have no predicate.

    name = post_data['%ssavedquery_name_%s' % (prefix, i)].strip()
    if not name:
      continue  # skip any blank entries

    if '%ssavedquery_id_%s' % (prefix, i) in post_data:
      query_id = int(post_data['%ssavedquery_id_%s' % (prefix, i)])
    else:
      query_id = None  # a new query_id will be generated by the DB.

    project_names_str = post_data.get(
        '%ssavedquery_projects_%s' % (prefix, i), '')
    project_names = [pn.strip().lower()
                     for pn in re.split('[],;\s]+', project_names_str)
                     if pn.strip()]
    project_ids = list(project_service.LookupProjectIDs(
        cnxn, project_names).values())

    base_id = int(post_data['%ssavedquery_base_%s' % (prefix, i)])
    query = post_data['%ssavedquery_query_%s' % (prefix, i)].strip()

    subscription_mode_field = '%ssavedquery_sub_mode_%s' % (prefix, i)
    if subscription_mode_field in post_data:
      subscription_mode = post_data[subscription_mode_field].strip()
    else:
      subscription_mode = None

    saved_queries.append(tracker_bizobj.MakeSavedQuery(
        query_id, name, base_id, query, subscription_mode=subscription_mode,
        executes_in_project_ids=project_ids))

  return saved_queries


class SavedQueryView(template_helpers.PBProxy):
  """Wrapper class that makes it easier to display SavedQuery via EZT."""

  def __init__(self, sq, idx, cnxn, project_service):
    """Store relevant values for later display by EZT.

    Args:
      sq: A SavedQuery protocol buffer.
      idx: Int index of this saved query in the list.
      cnxn: connection to SQL database.
      project_service: persistence layer for project data.
    """
    super(SavedQueryView, self).__init__(sq)

    self.idx = idx
    base_query_name = 'All issues'
    for canned in tracker_constants.DEFAULT_CANNED_QUERIES:
      qid, name, _base_id, _query = canned
      if qid == sq.base_query_id:
        base_query_name = name

    if cnxn:
      project_names = sorted(project_service.LookupProjectNames(
          cnxn, sq.executes_in_project_ids).values())
      self.projects = ', '.join(project_names)
    else:
      self.projects = ''

    self.docstring = '[%s] %s' % (base_query_name, sq.query)


def SavedQueryToCond(saved_query):
  """Convert a SavedQuery PB to a user query condition string."""
  if saved_query is None:
    return ''

  base_cond = tracker_bizobj.GetBuiltInQuery(saved_query.base_query_id)
  cond = '%s %s' % (base_cond, saved_query.query)
  return cond.strip()


def SavedQueryIDToCond(cnxn, features_service, query_id):
  """Convert a can/query ID to a user query condition string."""
  built_in = tracker_bizobj.GetBuiltInQuery(query_id)
  if built_in:
    return built_in

  saved_query = features_service.GetSavedQuery(cnxn, query_id)
  return SavedQueryToCond(saved_query)
