import hashlib
import os
import sys
# when pylint runs the third_party module is the one from depot_tools
# pylint: disable=E0611
from third_party import fancy_urllib
import urllib2


SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))


def UrlOpen(url):
  request = fancy_urllib.FancyRequest(url)
  ca_certs = os.path.join(SCRIPT_DIR, 'cacerts.txt')
  request.set_ssl_info(ca_certs=ca_certs)
  url_opener = urllib2.build_opener(
      fancy_urllib.FancyProxyHandler(),
      fancy_urllib.FancyRedirectHandler(),
      fancy_urllib.FancyHTTPSHandler())
  return url_opener.open(request)


def MakeProgressFunction(file_size=0):
  # An inner function can only read nonlocal variables, not assign them. We can
  # work around this by using a list of one element.
  dots = [0]
  def ShowKnownProgress(progress):
    '''Returns a progress function based on a known file size'''
    if progress == 0:
      sys.stdout.write('|%s|\n' % ('=' * 48))
    else:
      new_dots = progress * 50 / file_size - dots[0]
      sys.stdout.write('.' * new_dots)
      dots[0] += new_dots
      if progress == file_size:
        sys.stdout.write('\n')
    sys.stdout.flush()

  return ShowKnownProgress


def DownloadAndComputeHash(from_stream, to_stream=None, progress_func=None):
  '''Read from from-stream and generate sha1 and size info.

  Args:
    from_stream:   An input stream that supports read.
    to_stream:     [optional] the data is written to to_stream if it is
                   provided.
    progress_func: [optional] A function used to report download progress. If
                   provided, progress_func is called with progress=0 at the
                   beginning of the download, periodically with progress=1
                   during the download, and progress=100 at the end.

  Return
    A tuple (sha1, size) where sha1 is a sha1-hash for the archive data and
    size is the size of the archive data in bytes.'''
  # Use a no-op progress function if none is specified.
  def progress_no_op(progress):
    pass
  if not progress_func:
    progress_func = progress_no_op

  sha1_hash = hashlib.sha1()
  size = 0
  progress_func(progress=0)
  while(1):
    data = from_stream.read(32768)
    if not data:
      break
    sha1_hash.update(data)
    size += len(data)
    if to_stream:
      to_stream.write(data)
    progress_func(size)

  progress_func(progress=100)
  return sha1_hash.hexdigest(), size
