#!/usr/bin/env python
# Copyright (c) 2012 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.

"""Retrieves all the output that the Swarm server has produced for requests with
that name.
"""

import json
import logging
import optparse
import sys
import threading
import time
import urllib

#from common import find_depot_tools  # pylint: disable=W0611
#
## From the depot tools
#import fix_encoding

import run_isolated


class Failure(Exception):
  """Generic failure."""
  pass


def get_test_keys(swarm_base_url, test_name, timeout):
  """Returns the Swarm test key for each shards of test_name."""
  assert isinstance(timeout, float)
  key_data = urllib.urlencode([('name', test_name)])
  url = '%s/get_matching_test_cases?%s' % (swarm_base_url, key_data)

  for i in range(run_isolated.URL_OPEN_MAX_ATTEMPTS):
    response = run_isolated.url_open(url, retry_404=True, timeout=timeout)
    if response is None:
      raise Failure(
          'Error: Unable to find any tests with the name, %s, on swarm server'
          % test_name)

    result = response.read()
    # TODO(maruel): Compare exact string.
    if 'No matching' in result:
      logging.warning('Unable to find any tests with the name, %s, on swarm '
                      'server' % test_name)
      if i != run_isolated.URL_OPEN_MAX_ATTEMPTS:
        run_isolated.HttpService.sleep_before_retry(i, None)
      continue
    return json.loads(result)

  raise Failure(
      'Error: Unable to find any tests with the name, %s, on swarm server'
      % test_name)


class Bit(object):
  """Thread safe setable bit."""
  _lock = threading.Lock()
  _value = False

  def get(self):
    with self._lock:
      return self._value

  def set(self):
    with self._lock:
      self._value = True


def now():
  """Exists so it can be mocked easily."""
  return time.time()


def retrieve_results(base_url, test_key, timeout, should_stop):
  """Retrieves results for a single test_key."""
  assert isinstance(timeout, float)
  params = [('r', test_key)]
  result_url = '%s/get_result?%s' % (base_url, urllib.urlencode(params))
  start = now()
  while True:
    if timeout and (now() - start) >= timeout:
      logging.warning('retrieve_results(%s) timed out', base_url)
      return {}
    # Do retries ourselve.
    response = run_isolated.url_open(
        result_url, retry_404=False, retry_50x=False)
    if response is None:
      # Aggressively poll for results. Do not use retry_404 so
      # should_stop is polled more often.
      remaining = min(5, timeout - (now() - start)) if timeout else 5
      if remaining > 0:
        run_isolated.HttpService.sleep_before_retry(1, remaining)