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

"""Contains classes used among bisect modules.

* Score: stores a list of scores and its statistics.
* CommitInfo: stores commit info.
* OptionsChecker: performs sanity check that every required option are given.
"""

from __future__ import division

import math

from chromite.lib import cros_logging as logging

class Score(object):
  """Stores a list of scores and calculates its statistics.

  Scores can be assigned by constructor or Update().

  Attributes:
    values: A list of scores.
    mean: Mean of the scores.
    variance: Variance of the scores.
    std: Standard deviation of the scores.
  """

  def __init__(self, values=None):
    """Constructor.

    If values is not assigned, e.g. Score(), it returns a default Score object.
    And bool(Score()) == False.

    Args:
      values: A list of scores.
    """
    self.values = []
    self.mean = 0.0
    self.variance = 0.0
    self.std = 0.0
    if values is not None:
      self.Update(values)

  def __repr__(self):
    return 'Score(values=%r)' % self.values

  def __str__(self):
    return 'Score(values=%r, mean=%.3f, var=%.3f, std=%.3f)' % (
        self.values, self.mean, self.variance, self.std)

  def __len__(self):
    """Returns number of scores.

    Returns:
      Number of values.
    """
    return len(self.values)

  def __eq__(self, other):
    return sorted(self.values) == sorted(other.values)

  def __ne__(self, other):
    return not self.__eq__(other)

  def Clear(self):
    """Clears values and statistics."""
    self.values = []
    self.mean = 0.0
    self.variance = 0.0
    self.std = 0.0

  def Update(self, values):
    """Updates scores and their corresponding statistics.

    If values is empty or ill-formed, it calls Clear().

    Args:
      values: a list of scores.
    """
    if not values:
      self.Clear()
      return
    try:
      values = [float(x) for x in values]
    except ValueError as e:
      logging.error('Invalid literal of score: %s', e)
      self.Clear()
      return
    except TypeError:
      logging.error('Invalid type of score: %s', values)
      self.Clear()
      return

    self.values = values
    num_values = len(values)
    if num_values == 1:
      self.mean = values[0]
      self.variance = 0.0
      self.std = 0.0
    else:
      self.mean = sum(values) / num_values
      differences_from_mean = [x - self.mean for x in values]
      squared_differences = [x * x for x in differences_from_mean]
      self.variance = sum(squared_differences) / (num_values - 1)
      self.std = math.sqrt(self.variance)


class CommitInfo(object):
  """Stores commit info.

  Attributes:
    sha1: Commit SHA1.
    title: Commit title.
    score: Evaluation score of the commit.
    label: 'good' or 'bad'.
    timestamp: Commit timestamp.
  """
  def __init__(self, sha1=None, title=None, score=None, label=None,
               timestamp=None):
    """Constructor.

    All arguments are optional. CommitInfo() creates default CommitInfo object
    and bool(CommitInfo()) == False.

    Args:
      sha1: Commit SHA1.
      title: Commit title.
      score: Evaluation score of the commit.
      label: 'good' or 'bad'.
      timestamp: Commit timestamp.
    """
    self.sha1 = '' if sha1 is None else sha1
    self.title = '' if title is None else title
    self.score = Score() if score is None else score
    self.label = '' if label is None else label
    self.timestamp = 0 if timestamp is None else timestamp

  def __repr__(self):
    return 'CommitInfo(sha1=%r, title=%r, score=%r, label=%r, timestamp=%r)' % (
        self.sha1, self.title, self.score, self.label, self.timestamp)

  def __eq__(self, other):
    return (self.sha1 == other.sha1 and self.title == other.title and
            self.score == other.score and self.label == other.label and
            self.timestamp == other.timestamp)

  def __ne__(self, other):
    return not self.__eq__(other)

  def __bool__(self):
    return bool(self.sha1 or self.timestamp or self.title or self.label or
                self.score)

  # Python 2 glue.
  __nonzero__ = __bool__


class MissingRequiredOptionsException(Exception):
  """Exception raised for missing required options."""


class OptionsChecker(object):
  """Makes sure that __init__'s 'options' contains all required arguments.

  Its derived class should just update class attribute "REQUIRED_ARGS" and
  invokes __init__ to get options checked. For example:
    class ClassA(OptionsChecker):
      REQUIRED_ARGS = ['a']
      def __init__(self, options):
        super(ClassA, self).__init__(options)

    class ClassB(ClassA):
      REQUIRED_ARGS = ClassA.REQUIRED_ARGS + ['b']
      def __init__(self, options):
        super(ClassB, self).__init__(options)

    then calling
      ClassA(argparse.Namespace(a='a'))
      ClassB(argparse.Namespace(a='a', b='b'))
    is okay, but calling
      ClassA(argparse.Namespace(c='c'))
      ClassB(argparse.Namespace(b='b'))
    raises MissingRequiredOptionsException telling you that argument a is
    missing.
  """
  REQUIRED_ARGS = ()

  def __init__(self, options):
    """Constructor.

    Args:
      options: An argparse.Namespace to hold command line arguments.

    Raises:
      MissingRequiredOptionsException if any required argument is missing.
    """
    self.SanityCheckOptions(options)

  @classmethod
  def SanityCheckOptions(cls, options):
    """Performs sanity check on command line arguments.

    Args:
      options: An argparse.Namespace to hold command line arguments.

    Returns:
      True if sanity check passed.

    Raises:
      MissingRequiredOptionsException if any required argument is missing.
    """
    missing_args = [arg for arg in cls.REQUIRED_ARGS if arg not in options]
    if missing_args:
      raise MissingRequiredOptionsException(
          'Missing command line argument(s) %s required for class %s' %
          (missing_args, cls.__name__))
    return True
