# Copyright 2018 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

"""A service for querying data for charts.

Functions for querying the IssueSnapshot table and associated join tables.
"""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import settings
import time

from features import hotlist_helpers
from framework import framework_helpers
from framework import sql
from search import search_helpers
from tracker import tracker_bizobj
from tracker import tracker_helpers
from search import query2ast
from search import ast2select
from search import ast2ast


ISSUESNAPSHOT_TABLE_NAME = 'IssueSnapshot'
ISSUESNAPSHOT2CC_TABLE_NAME = 'IssueSnapshot2Cc'
ISSUESNAPSHOT2COMPONENT_TABLE_NAME = 'IssueSnapshot2Component'
ISSUESNAPSHOT2LABEL_TABLE_NAME = 'IssueSnapshot2Label'

ISSUESNAPSHOT_COLS = ['id', 'issue_id', 'shard', 'project_id', 'local_id',
    'reporter_id', 'owner_id', 'status_id', 'period_start', 'period_end',
    'is_open']
ISSUESNAPSHOT2CC_COLS = ['issuesnapshot_id', 'cc_id']
ISSUESNAPSHOT2COMPONENT_COLS = ['issuesnapshot_id', 'component_id']
ISSUESNAPSHOT2LABEL_COLS = ['issuesnapshot_id', 'label_id']


class ChartService(object):
  """Class for querying chart data."""

  def __init__(self, config_service):
    """Constructor for ChartService.

    Args:
      config_service (ConfigService): An instance of ConfigService.
    """
    self.config_service = config_service

    # Set up SQL table objects.
    self.issuesnapshot_tbl = sql.SQLTableManager(ISSUESNAPSHOT_TABLE_NAME)
    self.issuesnapshot2cc_tbl = sql.SQLTableManager(
        ISSUESNAPSHOT2CC_TABLE_NAME)
    self.issuesnapshot2component_tbl = sql.SQLTableManager(
        ISSUESNAPSHOT2COMPONENT_TABLE_NAME)
    self.issuesnapshot2label_tbl = sql.SQLTableManager(
        ISSUESNAPSHOT2LABEL_TABLE_NAME)

  def QueryIssueSnapshots(self, cnxn, services, unixtime, effective_ids,
                          project, perms, group_by=None, label_prefix=None,
                          query=None, canned_query=None, hotlist=None):
    """Queries historical issue counts grouped by label or component.

    Args:
      cnxn: A MonorailConnection instance.
      services: A Services instance.
      unixtime: An integer representing the Unix time in seconds.
      effective_ids: The effective User IDs associated with the current user.
      project: A project object representing the current project.
      perms: A permissions object associated with the current user.
      group_by (str, optional): Which dimension to group by. Values can
        be 'label', 'component', or None, in which case no grouping will
        be applied.
      label_prefix: Required when group_by is 'label.' Will limit the query to
        only labels with the specified prefix (for example 'Pri').
      query (str, optional): A query string from the request to apply to
        the snapshot query.
      canned_query (str, optional): Parsed canned query applied to the query
        scope.
      hotlist (Hotlist, optional): Hotlist to search under (in lieu of project).

    Returns:
      1. A dict of {'2nd dimension or "total"': number of occurences}.
      2. A list of any unsupported query conditions in query.
      3. A boolean that is true if any results were capped.
    """
    if hotlist:
      # TODO(jeffcarp): Get project_ids in a more efficient manner. We can
      #   query for "SELECT DISTINCT(project_id)" for all issues in hotlist.
      issues_list = services.issue.GetIssues(cnxn,
          [hotlist_issue.issue_id for hotlist_issue in hotlist.items])
      hotlist_issues_project_ids = hotlist_helpers.GetAllProjectsOfIssues(
          [issue for issue in issues_list])
      config_list = hotlist_helpers.GetAllConfigsOfProjects(
          cnxn, hotlist_issues_project_ids, services)
      project_config = tracker_bizobj.HarmonizeConfigs(config_list)
    else:
      project_config = services.config.GetProjectConfig(cnxn,
          project.project_id)

    if project:
      project_ids = [project.project_id]
    else:
      project_ids = hotlist_issues_project_ids

    try:
      query_left_joins, query_where, unsupported_conds = self._QueryToWhere(
          cnxn, services, project_config, query, canned_query, project_ids)
    except ast2select.NoPossibleResults:
      return {}, ['Invalid query.'], False

    restricted_label_ids = search_helpers.GetPersonalAtRiskLabelIDs(
      cnxn, None, self.config_service, effective_ids, project, perms)

    left_joins = [
      ('Issue ON IssueSnapshot.issue_id = Issue.id', []),
    ]

    if restricted_label_ids:
      left_joins.append(
        (('Issue2Label AS Forbidden_label'
          ' ON Issue.id = Forbidden_label.issue_id'
          ' AND Forbidden_label.label_id IN (%s)' % (
            sql.PlaceHolders(restricted_label_ids)
        )), restricted_label_ids))

    if effective_ids:
      left_joins.append(
        ('Issue2Cc AS I2cc'
         ' ON Issue.id = I2cc.issue_id'
         ' AND I2cc.cc_id IN (%s)' % sql.PlaceHolders(effective_ids),
         effective_ids))

    # TODO(jeffcarp): Handle case where there are issues with no labels.
    where = [
      ('IssueSnapshot.period_start <= %s', [unixtime]),
      ('IssueSnapshot.period_end > %s', [unixtime]),
      ('Issue.is_spam = %s', [False]),
      ('Issue.deleted = %s', [False]),
    ]
    if project_ids:
      where.append(
        ('IssueSnapshot.project_id IN (%s)' % sql.PlaceHolders(project_ids),
          project_ids))

    forbidden_label_clause = 'Forbidden_label.label_id IS NULL'
    if effective_ids:
      if restricted_label_ids:
        forbidden_label_clause = ' OR %s' % forbidden_label_clause
      else:
        forbidden_label_clause =  ''

      where.append(
        ((
          '(Issue.reporter_id IN (%s)'
          ' OR Issue.owner_id IN (%s)'
          ' OR I2cc.cc_id IS NOT NULL'
          '%s)'
        ) % (
          sql.PlaceHolders(effective_ids), sql.PlaceHolders(effective_ids),
          forbidden_label_clause
        ),
          list(effective_ids) + list(effective_ids)
        ))
    else:
      where.append((forbidden_label_clause, []))

    if group_by == 'component':
      cols = ['Comp.path', 'COUNT(IssueSnapshot.issue_id)']
      left_joins.extend([
        (('IssueSnapshot2Component AS Is2c ON'
          ' Is2c.issuesnapshot_id = IssueSnapshot.id'), []),
        ('ComponentDef AS Comp ON Comp.id = Is2c.component_id', []),
      ])
      group_by = ['Comp.path']
    elif group_by == 'label':
      cols = ['Lab.label', 'COUNT(IssueSnapshot.issue_id)']
      left_joins.extend([
        (('IssueSnapshot2Label AS Is2l'
          ' ON Is2l.issuesnapshot_id = IssueSnapshot.id'), []),
        ('LabelDef AS Lab ON Lab.id = Is2l.label_id', []),
      ])

      if not label_prefix:
        raise ValueError('`label_prefix` required when grouping by label.')

      # TODO(jeffcarp): If LookupIDsOfLabelsMatching() is called on output,
      # ensure regex is case-insensitive.
      where.append(('LOWER(Lab.label) LIKE %s', [label_prefix.lower() + '-%']))
      group_by = ['Lab.label']
    elif group_by == 'open':
      cols = ['IssueSnapshot.is_open',
        'COUNT(IssueSnapshot.issue_id) AS issue_count']
      group_by = ['IssueSnapshot.is_open']
    elif group_by == 'status':
      left_joins.append(('StatusDef AS Stats ON ' \
        'Stats.id = IssueSnapshot.status_id', []))
      cols = ['Stats.status', 'COUNT(IssueSnapshot.issue_id)']
      group_by = ['Stats.status']
    elif group_by == 'owner':
      cols = ['IssueSnapshot.owner_id', 'COUNT(IssueSnapshot.issue_id)']
      group_by = ['IssueSnapshot.owner_id']
    elif not group_by:
      cols = ['IssueSnapshot.issue_id']
    else:
      raise ValueError('`group_by` must be label, component, ' \
        'open, status, owner or None.')

    if query_left_joins:
      left_joins.extend(query_left_joins)

    if query_where:
      where.extend(query_where)

    if hotlist:
      left_joins.extend([
        (('IssueSnapshot2Hotlist AS Is2h'
          ' ON Is2h.issuesnapshot_id = IssueSnapshot.id'
          ' AND Is2h.hotlist_id = %s'), [hotlist.hotlist_id]),
      ])
      where.append(
        ('Is2h.hotlist_id = %s', [hotlist.hotlist_id]))

    promises = []

    for shard_id in range(settings.num_logical_shards):
      count_stmt, stmt_args = self._BuildSnapshotQuery(cols=cols,
          where=where, joins=left_joins, group_by=group_by,
          shard_id=shard_id)
      promises.append(framework_helpers.Promise(cnxn.Execute,
          count_stmt, stmt_args, shard_id=shard_id))

    shard_values_dict = {}

    search_limit_reached = False

    for promise in promises:
      # Wait for each query to complete and add it to the dict.
      shard_values = list(promise.WaitAndGetValue())

      if not shard_values:
        continue
      if group_by:
        for name, count in shard_values:
          if count >= settings.chart_query_max_rows:
            search_limit_reached = True

          shard_values_dict.setdefault(name, 0)
          shard_values_dict[name] += count
      else:
        if shard_values[0][0] >= settings.chart_query_max_rows:
            search_limit_reached = True

        shard_values_dict.setdefault('total', 0)
        shard_values_dict['total'] += shard_values[0][0]

    unsupported_field_names = list(set([
        field.field_name
        for cond in unsupported_conds
        for field in cond.field_defs
    ]))

    return shard_values_dict, unsupported_field_names, search_limit_reached

  def StoreIssueSnapshots(self, cnxn, issues, commit=True):
    """Adds an IssueSnapshot and updates the previous one for each issue."""
    for issue in issues:
      right_now = self._currentTime()

      # Update previous snapshot of current issue's end time to right now.
      self.issuesnapshot_tbl.Update(cnxn,
          delta={'period_end': right_now},
          where=[('IssueSnapshot.issue_id = %s', [issue.issue_id]),
            ('IssueSnapshot.period_end = %s',
              [settings.maximum_snapshot_period_end])],
          commit=commit)

      config = self.config_service.GetProjectConfig(cnxn, issue.project_id)
      period_end = settings.maximum_snapshot_period_end
      is_open = tracker_helpers.MeansOpenInProject(
        tracker_bizobj.GetStatus(issue), config)
      shard = issue.issue_id % settings.num_logical_shards
      status = tracker_bizobj.GetStatus(issue)
      status_id = self.config_service.LookupStatusID(
          cnxn, issue.project_id, status) or None
      owner_id = tracker_bizobj.GetOwnerId(issue) or None

      issuesnapshot_rows = [(issue.issue_id, shard, issue.project_id,
        issue.local_id, issue.reporter_id, owner_id, status_id, right_now,
        period_end, is_open)]

      ids = self.issuesnapshot_tbl.InsertRows(
          cnxn, ISSUESNAPSHOT_COLS[1:],
          issuesnapshot_rows,
          replace=True, commit=commit,
          return_generated_ids=True)
      issuesnapshot_id = ids[0]

      # Add all labels to IssueSnapshot2Label.
      label_rows = [
          (issuesnapshot_id,
           self.config_service.LookupLabelID(cnxn, issue.project_id, label))
          for label in tracker_bizobj.GetLabels(issue)
      ]
      self.issuesnapshot2label_tbl.InsertRows(
          cnxn, ISSUESNAPSHOT2LABEL_COLS,
          label_rows, replace=True, commit=commit)

      # Add all CCs to IssueSnapshot2Cc.
      cc_rows = [
        (issuesnapshot_id, cc_id)
        for cc_id in tracker_bizobj.GetCcIds(issue)
      ]
      self.issuesnapshot2cc_tbl.InsertRows(
          cnxn, ISSUESNAPSHOT2CC_COLS,
          cc_rows,
          replace=True, commit=commit)

      # Add all components to IssueSnapshot2Component.
      component_rows = [
        (issuesnapshot_id, component_id)
        for component_id in issue.component_ids
      ]
      self.issuesnapshot2component_tbl.InsertRows(
          cnxn, ISSUESNAPSHOT2COMPONENT_COLS,
          component_rows,
          replace=True, commit=commit)

      # Add all components to IssueSnapshot2Hotlist.
      # This is raw SQL to obviate passing FeaturesService down through
      #   the call stack wherever this function is called.
      # TODO(jrobbins): sort out dependencies between service classes.
      cnxn.Execute('''
        INSERT INTO IssueSnapshot2Hotlist (issuesnapshot_id, hotlist_id)
        SELECT %s, hotlist_id FROM Hotlist2Issue WHERE issue_id = %s
      ''', [issuesnapshot_id, issue.issue_id])

  def ExpungeHotlistsFromIssueSnapshots(self, cnxn, hotlist_ids, commit=True):
    """Expunge the existence of hotlists from issue snapshots.

    Args:
      cnxn: connection to SQL database.
      hotlist_ids: list of hotlist_ids for hotlists we want to delete.
      commit: set to False to skip the DB commit and do it in a caller.
    """
    vals_ph = sql.PlaceHolders(hotlist_ids)
    cnxn.Execute(
        'DELETE FROM IssueSnapshot2Hotlist '
        'WHERE hotlist_id IN ({vals_ph})'.format(vals_ph=vals_ph),
        hotlist_ids,
        commit=commit)

  def _currentTime(self):
    """This is a separate method so it can be mocked by tests."""
    return time.time()

  def _QueryToWhere(self, cnxn, services, project_config, query, canned_query,
                    project_ids):
    """Parses a query string into LEFT JOIN and WHERE conditions.

    Args:
      cnxn: A MonorailConnection instance.
      services: A Services instance.
      project_config: The configuration for the given project.
      query (string): The query to parse.
      canned_query (string): The supplied canned query.
      project_ids: The current project ID(s).

    Returns:
      1. A list of LEFT JOIN clauses for the SQL query.
      2. A list of WHERE clases for the SQL query.
      3. A list of query conditions that are unsupported with snapshots.
    """
    if not (query or canned_query):
      return [], [], []

    query = query or ''
    scope = canned_query or ''

    query_ast = query2ast.ParseUserQuery(query, scope,
        query2ast.BUILTIN_ISSUE_FIELDS, project_config)
    query_ast = ast2ast.PreprocessAST(cnxn, query_ast, project_ids,
        services, project_config)
    left_joins, where, unsupported = ast2select.BuildSQLQuery(query_ast,
        snapshot_mode=True)

    return left_joins, where, unsupported

  def _BuildSnapshotQuery(self, cols, where, joins, group_by, shard_id):
    """Given SQL arguments, executes a snapshot COUNT query."""
    stmt = sql.Statement.MakeSelect('IssueSnapshot', cols, distinct=True)
    stmt.AddJoinClauses(joins, left=True)
    stmt.AddWhereTerms(where + [('IssueSnapshot.shard = %s', [shard_id])])
    if group_by:
      stmt.AddGroupByTerms(group_by)
    stmt.SetLimitAndOffset(limit=settings.chart_query_max_rows, offset=0)
    stmt_str, stmt_args = stmt.Generate()
    if group_by:
      if group_by[0] == 'IssueSnapshot.is_open':
        count_stmt = ('SELECT IF(results.is_open = 1, "Opened", "Closed") ' \
          'AS bool_open, results.issue_count ' \
          'FROM (%s) AS results' % stmt_str)
      else:
        count_stmt = stmt_str
    else:
      count_stmt = 'SELECT COUNT(results.issue_id) FROM (%s) AS results' % (
        stmt_str)
    return count_stmt, stmt_args
