# Copyright 2015 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.

"""A Model that represents one bisect or perf test try job.

TryJob entities are checked in /update_bug_with_results to check completed
bisect jobs and update bugs with results.

They are also used in /auto_bisect to restart unsuccessful bisect jobs.
"""

import datetime
import json
import logging

from google.appengine.ext import ndb

from dashboard import bisect_stats
from dashboard import buildbucket_service
from dashboard.models import bug_data
from dashboard.models import internal_only_model


class TryJob(internal_only_model.InternalOnlyModel):
  """Stores config and tracking info about a single try job."""
  bot = ndb.StringProperty()
  config = ndb.TextProperty()
  bug_id = ndb.IntegerProperty()
  email = ndb.StringProperty()
  rietveld_issue_id = ndb.IntegerProperty()
  rietveld_patchset_id = ndb.IntegerProperty()
  master_name = ndb.StringProperty(default='ChromiumPerf', indexed=False)
  buildbucket_job_id = ndb.StringProperty()
  internal_only = ndb.BooleanProperty(default=False, indexed=True)

  # Bisect run status (e.g., started, failed).
  status = ndb.StringProperty(
      default='pending',
      choices=[
          'pending',  # Created, but job start has not been confirmed.
          'started',  # Job is confirmed started.
          'failed',   # Job terminated, red build.
          'staled',   # No updates from bots.
          'completed',  # Job terminated, green build.
          'aborted',  # Job terminated with abort (purple, early abort).
      ],
      indexed=True)

  # Number of times this job has been tried.
  run_count = ndb.IntegerProperty(default=0)

  # Last time this job was started.
  last_ran_timestamp = ndb.DateTimeProperty()

  job_type = ndb.StringProperty(
      default='bisect',
      choices=['bisect', 'bisect-fyi', 'perf-try'])

  # job_name attribute is used by try jobs of bisect FYI.
  job_name = ndb.StringProperty(default=None)

  # Results data coming from bisect bots.
  results_data = ndb.JsonProperty(indexed=False)

  log_record_id = ndb.StringProperty(indexed=False)

  # Sets of emails of users who has confirmed this TryJob result is bad.
  bad_result_emails = ndb.PickleProperty()

  def SetStarted(self):
    self.status = 'started'
    self.run_count += 1
    self.last_ran_timestamp = datetime.datetime.now()
    self.put()
    if self.bug_id:
      bug_data.SetBisectStatus(self.bug_id, 'started')

  def SetFailed(self):
    self.status = 'failed'
    self.put()
    if self.bug_id:
      bug_data.SetBisectStatus(self.bug_id, 'failed')
    bisect_stats.UpdateBisectStats(self.bot, 'failed')

  def SetStaled(self):
    self.status = 'staled'
    self.put()
    logging.info('Updated status to staled')
    # TODO(sullivan, dtu): what is the purpose of 'staled' status? Doesn't it
    # just prevent updating jobs older than 24 hours???
    # TODO(chrisphan): Add 'staled' state to bug_data and bisect_stats.
    if self.bug_id:
      bug_data.SetBisectStatus(self.bug_id, 'failed')
    bisect_stats.UpdateBisectStats(self.bot, 'failed')

  def SetCompleted(self):
    logging.info('Updated status to completed')
    self.status = 'completed'
    self.put()
    if self.bug_id:
      bug_data.SetBisectStatus(self.bug_id, 'completed')
    bisect_stats.UpdateBisectStats(self.bot, 'completed')

  def GetConfigDict(self):
    return json.loads(self.config.split('=', 1)[1])

  def CheckFailureFromBuildBucket(self):
    # Buildbucket job id is not always set.
    if not self.buildbucket_job_id:
      return
    job_info = buildbucket_service.GetJobStatus(self.buildbucket_job_id)
    data = job_info.get('build', {})

    # Since the job is completed successfully, results_data must
    # have been set appropriately by the bisector.
    # The buildbucket job's 'status' and 'result' fields are documented here:
    # https://goto.google.com/bb_status
    if data.get('status') == 'COMPLETED' and data.get('result') == 'SUCCESS':
      return

    # Proceed if the job failed or cancelled
    logging.info('Job failed. Buildbucket id %s', self.buildbucket_job_id)
    data['result_details'] = json.loads(data['result_details_json'])
    # There are various failure and cancellation reasons for a buildbucket
    # job to fail as listed in https://goto.google.com/bb_status.
    job_updates = {
        'status': 'failed',
        'failure_reason': (data.get('cancelation_reason') or
                           data.get('failure_reason')),
        'buildbot_log_url': data.get('url')
    }
    details = data.get('result_details')
    if details:
      properties = details.get('properties')
      if properties:
        job_updates['bisect_bot'] = properties.get('buildername')
        job_updates['extra_result_code'] = properties.get(
            'extra_result_code')
        bisect_config = properties.get('bisect_config')
        if bisect_config:
          job_updates['try_job_id'] = bisect_config.get('try_job_id')
          job_updates['bug_id'] = bisect_config.get('bug_id')
          job_updates['command'] = bisect_config.get('command')
          job_updates['test_type'] = bisect_config.get('test_type')
          job_updates['metric'] = bisect_config.get('metric')
          job_updates['good_revision'] = bisect_config.get('good_revision')
          job_updates['bad_revision'] = bisect_config.get('bad_revision')
    if not self.results_data:
      self.results_data = {}
    self.results_data.update(job_updates)
    self.status = 'failed'
    self.last_ran_timestamp = datetime.datetime.fromtimestamp(
        float(data['updated_ts'])/1000000)
    self.put()
    logging.info('updated status to failed.')

