# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Module to manage local build state."""

import json
import logging

from chromite.lib import constants
from chromite.utils import pformat


class BuildSummary(object):
  """Summarizes a build state without any external references.

  This is basically a dictionary that can convert itself back and forth from
  JSON, but it provides the convenience of attribute-based access instead of
  carrying around dictionary key constants.

  Attributes:
    build_number: The build number of this build, as passed in with
        --buildnumber, or 0 if --buildnumber wasn't passed.
    buildbucket_id: The buildbucket id of this build, as passed in with
        --buildbucket-id, or 0 if --buildbucket-id wasn't passed.
    master_build_id: The CIDB id of the associated master build if there is one,
        or 0 if there isn't one.
    status: One of the status constants from
        chromite.lib.constants.BUILDER_ALL_STATUSES
    buildroot_layout: Version of the buildroot layout.
    branch: Name of the branch this repository is associated with.
    distfiles_ts: Float unix timestamp recording the last time the distfiles
        cache was cleaned.
  """

  # List of attributes that should be saved and restored to represent
  # this object.  We use an explicit list instead of vars() so that future
  # additions can be handled explicitly.
  _PERSIST_ATTRIBUTES = ('build_number', 'buildbucket_id', 'master_build_id',
                         'status', 'buildroot_layout', 'branch', 'distfiles_ts')

  def __init__(self, build_number=0, buildbucket_id=0, master_build_id=0,
               status=constants.BUILDER_STATUS_MISSING,
               buildroot_layout=0, branch='', distfiles_ts=None):
    self.build_number = build_number
    self.buildbucket_id = buildbucket_id
    self.master_build_id = master_build_id
    self.status = status
    self.buildroot_layout = buildroot_layout
    self.branch = branch
    self.distfiles_ts = distfiles_ts

  def __eq__(self, other):
    for a in self._PERSIST_ATTRIBUTES:
      if hasattr(other, a) != hasattr(self, a):
        return False
      if getattr(other, a) != getattr(self, a):
        return False
    return True

  def __repr__(self):
    return 'BuildSummary(%s)' % self.to_json()

  def from_json(self, raw_json):
    """Merge the state encoded in |raw_json| into this object.

    Unknown keys will be ignored (with a warning).  Values for missing keys will
    remain unchanged.

    Args:
      raw_json: String containing valid JSON representing a BuildSummary.

    Raises:
      ValueError: |raw_json| is not valid JSON.
    """
    new_state = json.loads(raw_json)
    for key, val in new_state.items():
      if key in self._PERSIST_ATTRIBUTES:
        setattr(self, key, val)
      else:
        logging.warning('Ignoring unrecognized JSON key "%s"', key)

    if self.status not in constants.BUILDER_ALL_STATUSES:
      logging.warning('Ingoring unknown build status "%s"', self.status)
      self.status = constants.BUILDER_STATUS_MISSING

  def to_json(self):
    """Serialize this object to JSON.

    Attributes that have an empty/zero value are omitted from the output.  The
    output of this function can be passed to from_json() to get back another
    BuildSummary with the same values.

    Returns:
      A string containing a JSON-encoded representation of this object.
    """
    state = {}
    for a in self._PERSIST_ATTRIBUTES:
      val = getattr(self, a)
      if val:
        state[a] = getattr(self, a)
    return pformat.json(state, compact=True)

  def is_valid(self):
    """Indicate whether this object has a valid status."""
    return self.status != constants.BUILDER_STATUS_MISSING

  def build_description(self):
    """Get a human-readable description of which build id is set.

    If multiple fields are set, buildbucket is preferred.  The result can be
    used for logging or display, but should not be parsed for database lookups.

    Returns:
      String describing which build id is set, or "local build" if none are set.
    """
    if self.buildbucket_id:
      return 'buildbucket_id=%s' % self.buildbucket_id
    if self.build_number:
      return 'build_number=%s' % self.build_number
    return 'local build'
