# 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

"""A class to handle cron requests to expunge doomed and deletable projects."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import logging
import time

from framework import jsonfeed

RUN_DURATION_LIMIT = 50 * 60  # 50 minutes


class Reap(jsonfeed.FlaskInternalTask):
  """Look for doomed and deletable projects and delete them."""

  def HandleRequest(self, mr):
    """Update/Delete doomed and deletable projects as needed.

    Args:
      mr: common information parsed from the HTTP request.

    Returns:
      Results dictionary in JSON format. The JSON will look like this:
      {
        'doomed_project_ids': <int>,
        'expunged_project_ids': <int>
      }
      doomed_project_ids are the projects which have been marked as deletable.
      expunged_project_ids are the projects that have either been completely
      expunged or are in the midst of being expunged.
    """
    doomed_project_ids = self._MarkDoomedProjects(mr.cnxn)
    expunged_project_ids = self._ExpungeDeletableProjects(mr.cnxn)
    return {
        'doomed_project_ids': doomed_project_ids,
        'expunged_project_ids': expunged_project_ids,
        }

  def _MarkDoomedProjects(self, cnxn):
    """No longer needed projects get doomed, and this marks them deletable."""
    now = int(time.time())
    doomed_project_rows = self.services.project.project_tbl.Select(
        cnxn, cols=['project_id'],
        # We only match projects with real timestamps and not delete_time = 0.
        where=[('delete_time < %s', [now]), ('delete_time != %s', [0])],
        state='archived', limit=1000)
    doomed_project_ids = [row[0] for row in doomed_project_rows]
    for project_id in doomed_project_ids:
      # Note: We go straight to services layer because this is an internal
      # request, not a request from a user.
      self.services.project.MarkProjectDeletable(
          cnxn, project_id, self.services.config)

    return doomed_project_ids

  def _ExpungeDeletableProjects(self, cnxn):
    """Chip away at deletable projects until they are gone."""
    request_deadline = time.time() + RUN_DURATION_LIMIT

    deletable_project_rows = self.services.project.project_tbl.Select(
        cnxn, cols=['project_id'], state='deletable', limit=100)
    deletable_project_ids = [row[0] for row in deletable_project_rows]
    # expunged_project_ids will contain projects that have either been
    # completely expunged or are in the midst of being expunged.
    expunged_project_ids = set()
    for project_id in deletable_project_ids:
      for _part in self._ExpungeParts(cnxn, project_id):
        expunged_project_ids.add(project_id)
        if time.time() > request_deadline:
          return list(expunged_project_ids)

    return list(expunged_project_ids)

  def _ExpungeParts(self, cnxn, project_id):
    """Delete all data from the specified project, one part at a time.

    This method purges all data associated with the specified project. The
    following is purged:
    * All issues of the project.
    * Project config.
    * Saved queries.
    * Filter rules.
    * Former locations.
    * Local ID counters.
    * Quick edit history.
    * Item stars.
    * Project from the DB.

    Returns a generator whose return values can be either issue
    ids or the specified project id. The returned values are intended to be
    iterated over and not read.
    """
    # Purge all issues of the project.
    while True:
      issue_id_rows = self.services.issue.issue_tbl.Select(
          cnxn, cols=['id'], project_id=project_id, limit=1000)
      issue_ids = [row[0] for row in issue_id_rows]
      for issue_id in issue_ids:
        self.services.issue_star.ExpungeStars(cnxn, issue_id)
      self.services.issue.ExpungeIssues(cnxn, issue_ids)
      yield issue_ids
      break

    # All project purge functions are called with cnxn and project_id.
    project_purge_functions = (
      self.services.config.ExpungeConfig,
      self.services.template.ExpungeProjectTemplates,
      self.services.features.ExpungeSavedQueriesExecuteInProject,
      self.services.features.ExpungeFilterRules,
      self.services.issue.ExpungeFormerLocations,
      self.services.issue.ExpungeLocalIDCounters,
      self.services.features.ExpungeQuickEditHistory,
      self.services.project_star.ExpungeStars,
      self.services.project.ExpungeProject,
    )

    for f in project_purge_functions:
      f(cnxn, project_id)
      yield project_id

  def GetReap(self, **kwargs):
    return self.handler(**kwargs)
