# Copyright (c) 2013 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.

"""Library for uploading command stats to AppEngine."""

from __future__ import print_function

import contextlib
import logging
import os
import parallel
import urllib
import urllib2

from chromite.cbuildbot import constants
from chromite.lib import cros_build_lib
from chromite.lib import git
from chromite.lib import osutils
from chromite.lib import timeout_util


class Stats(object):
  """Entity object for a stats entry."""

  # These attributes correspond to the fields of a stats record.
  __slots__ = (
      'board',
      'cmd_args',
      'cmd_base',
      'cmd_line',
      'cpu_count',
      'cpu_type',
      'host',
      'package_count',
      'run_time',
      'username',
  )

  def __init__(self, **kwargs):
    """Initialize the record.

    **kwargs keys need to correspond to elements in __slots__.  These arguments
    can be lists:
    - cmd_args
    - cmd_base
    - cmd_line

    If unset, the |username| and |host|  attributes will be determined
    automatically.
    """
    if kwargs.get('username') is None:
      kwargs['username'] = git.GetProjectUserEmail(os.path.dirname(__file__))

    if kwargs.get('host') is None:
      kwargs['host'] = cros_build_lib.GetHostName(fully_qualified=True)

    for attr in ('cmd_args', 'cmd_base', 'cmd_line'):
      val = kwargs.get(attr)
      if isinstance(val, (list, tuple,)):
        kwargs[attr] = ' '.join(map(repr, val))

    for arg in self.__slots__:
      setattr(self, arg, kwargs.pop(arg, None))
    if kwargs:
      raise TypeError('Unknown options specified %r:' % kwargs)

  @property
  def data(self):
    """Retrieves a dictionary representing the fields that are set."""
    data = {}
    for arg in self.__slots__:
      val = getattr(self, arg)
      if val is not None:
        data[arg] = val
    return data

  @classmethod
  def SafeInit(cls, **kwargs):
    """Construct a Stats object, catching any exceptions.

    See Stats.__init__() for argument list.

    Returns:
      A Stats() instance if things went smoothly, and None if exceptions were
      caught in the process.
    """
    try:
      inst = cls(**kwargs)
    except Exception:
      logging.error('Exception during stats upload.', exc_info=True)
    else:
      return inst


class StatsUploader(object):
  """Functionality to upload the stats to the AppEngine server."""

  # To test with an app engine instance on localhost, set envvar
  # export CROS_BUILD_STATS_SITE="http://localhost:8080"
  _PAGE = 'upload_command_stats'
  _DEFAULT_SITE = 'https://chromiumos-build-stats.appspot.com'
  _SITE = os.environ.get('CROS_BUILD_STATS_SITE', _DEFAULT_SITE)
  URL = '%s/%s' % (_SITE, _PAGE)
  UPLOAD_TIMEOUT = 5

  _DISABLE_FILE = '~/.disable_build_stats_upload'

  _DOMAIN_WHITELIST = (constants.CORP_DOMAIN, constants.GOLO_DOMAIN)
  _EMAIL_WHITELIST = (constants.GOOGLE_EMAIL, constants.CHROMIUM_EMAIL)

  TIMEOUT_ERROR = 'Timed out during command stat upload - waited %s seconds'
  ENVIRONMENT_ERROR = 'Exception during command stat upload.'
  HTTPURL_ERROR = 'Exception during command stat upload to %s.'

  @classmethod
  def _UploadConditionsMet(cls, stats):
    """Return True if upload conditions are met."""
    def CheckDomain(hostname):
      return any(hostname.endswith(d) for d in cls._DOMAIN_WHITELIST)

    def CheckEmail(email):
      return any(email.endswith(e) for e in cls._EMAIL_WHITELIST)

    upload = False

    # Verify that host domain is in golo.chromium.org or corp.google.com.
    if not stats.host or not CheckDomain(stats.host):
      logging.debug('Host %s is not a Google machine.', stats.host)
    elif not stats.username:
      logging.debug('Unable to determine current "git id".')
    elif not CheckEmail(stats.username):
      logging.debug('%s is not a Google or Chromium user.', stats.username)
    elif os.path.exists(osutils.ExpandPath(cls._DISABLE_FILE)):
      logging.debug('Found %s', cls._DISABLE_FILE)
    else:
      upload = True

    if not upload:
      logging.debug('Skipping stats upload.')

    return upload

  @classmethod
  def Upload(cls, stats, url=None, timeout=None):
    """Upload |stats| to |url|.

    Does nothing if upload conditions aren't met.

    Args:
      stats: A Stats object to upload.
      url: The url to send the request to.
      timeout: A timeout value to set, in seconds.
    """
    if url is None:
      url = cls.URL
    if timeout is None:
      timeout = cls.UPLOAD_TIMEOUT

    if not cls._UploadConditionsMet(stats):
      return

    with timeout_util.Timeout(timeout):
      try:
        cls._Upload(stats, url)
      # Stats upload errors are silenced, for the sake of user experience.
      except timeout_util.TimeoutError:
        logging.debug(cls.TIMEOUT_ERROR, timeout)
      except urllib2.HTTPError as e:
        # HTTPError has a geturl() method, but it relies on self.url, which
        # is not always set.  In looking at source, self.filename equals url.
        logging.debug(cls.HTTPURL_ERROR, e.filename, exc_info=True)
      except EnvironmentError:
        logging.debug(cls.ENVIRONMENT_ERROR, exc_info=True)

  @classmethod
  def _Upload(cls, stats, url):
    logging.debug('Uploading command stats to %r', url)
    data = urllib.urlencode(stats.data)
    request = urllib2.Request(url)
    urllib2.urlopen(request, data)


UNCAUGHT_UPLOAD_ERROR = 'Uncaught command stats exception'


@contextlib.contextmanager
def UploadContext():
  """Provides a context where stats are uploaded in the background.

  Yields:
    A queue that accepts an arg-list of the format [stats, url, timeout].
  """
  try:
    # We need to use parallel.BackgroundTaskRunner, and not
    # parallel.RunParallelTasks, because with RunParallelTasks, both the
    # uploader and the subcommand are treated as background tasks, and the
    # subcommand will lose responsiveness, since its output will be buffered.
    with parallel.BackgroundTaskRunner(
        StatsUploader.Upload, processes=1) as queue:
      yield queue
  except parallel.BackgroundFailure:
    # Display unexpected errors, but don't propagate the error.
    logging.error('Uncaught command stats exception', exc_info=True)
