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

import atexit
import datetime
import email.utils
import errno
import gzip
import hashlib
import logging
import math
import os.path
import shutil
import socket
import threading
import tempfile

import SimpleHTTPServer
import SocketServer

_ZERO = datetime.timedelta(0)


class UTC_TZINFO(datetime.tzinfo):
  """UTC time zone representation."""

  def utcoffset(self, _):
    return _ZERO

  def tzname(self, _):
    return "UTC"

  def dst(self, _):
     return _ZERO

_UTC = UTC_TZINFO()


class _SilentTCPServer(SocketServer.TCPServer):
  """A TCPServer that won't display any error, unless debugging is enabled. This
  is useful because the client might stop while it is fetching an URL, which
  causes spurious error messages.
  """
  allow_reuse_address = True

  def handle_error(self, request, client_address):
    """Override the base class method to have conditional logging."""
    if logging.getLogger().isEnabledFor(logging.DEBUG):
      SocketServer.TCPServer.handle_error(self, request, client_address)


def _get_handler_class_for_path(mappings):
  """Creates a handler override for SimpleHTTPServer.

  Args:
    mappings: List of tuples (prefix, local_base_path_list) mapping URLs that
        start with |prefix| to one or more local directories enumerated in
        |local_base_path_list|. The prefixes should skip the leading slash.
        The first matching prefix and the first location that contains the
        requested file will be used each time.
  """
  for prefix, _ in mappings:
    assert not prefix.startswith('/'), ('Prefixes for the http server mappings '
                                        'should skip the leading slash.')

  class RequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    """Handler for SocketServer.TCPServer that will serve the files from
    local directiories over http.

    A new instance is created for each request.
    """

    def __init__(self, *args, **kwargs):
      self.etag = None
      self.gzipped_file = None
      self.original_file_name = None
      SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)

    def get_etag(self):
      if self.etag:
        return self.etag

      path = self.translate_path(self.path, False)
      if not os.path.isfile(path):
        return None

      sha256 = hashlib.sha256()
      BLOCKSIZE = 65536
      with open(path, 'rb') as hashed:
        buf = hashed.read(BLOCKSIZE)
        while len(buf) > 0:
          sha256.update(buf)
          buf = hashed.read(BLOCKSIZE)
      self.etag = '"%s"' % sha256.hexdigest()
      return self.etag

    def send_head(self):
      # Always close the connection after each request, as the keep alive
      # support from SimpleHTTPServer doesn't like when the client requests to
      # close the connection before downloading the full response content.
      # pylint: disable=W0201
      self.close_connection = 1

      path = self.translate_path(self.path)
      if os.path.isfile(path):
        # Handle If-None-Match
        etag = self.get_etag()
        if ('If-None-Match' in self.headers and
            etag == self.headers['If-None-Match']):
          self.send_response(304)
          return None

        # Handle If-Modified-Since
        if ('If-None-Match' not in self.headers and
            'If-Modified-Since' in self.headers):
          last_modified = datetime.datetime.fromtimestamp(
              math.floor(os.stat(path).st_mtime), tz=_UTC)
          ims = datetime.datetime(
              *email.utils.parsedate(self.headers['If-Modified-Since'])[:6],
              tzinfo=_UTC)
          if last_modified <= ims:
            self.send_response(304)
            return None

      return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)

    def end_headers(self):
      path = self.translate_path(self.path)

      if os.path.isfile(path):
        self.send_header('Content-Encoding', 'gzip')
        etag = self.get_etag()
        if etag:
          self.send_header('ETag', etag)
          self.send_header('Cache-Control', 'must-revalidate')

      return SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self)

    # pylint: disable=W0221
    def translate_path(self, path, gzipped=True):
      # Parent translate_path() will strip away the query string and fragment
      # identifier, but also will prepend the cwd to the path. relpath() gives
      # us the relative path back.
      normalized_path = os.path.relpath(
          SimpleHTTPServer.SimpleHTTPRequestHandler.translate_path(self, path))

      for prefix, local_base_path_list in mappings:
        if normalized_path.startswith(prefix):
          for local_base_path in local_base_path_list:
            candidate = os.path.join(local_base_path,
                                     normalized_path[len(prefix):])
            if os.path.isfile(candidate):
              if gzipped:
                if not self.gzipped_file:
                  self.gzipped_file = tempfile.NamedTemporaryFile(delete=False)
                  self.original_file_name = candidate
                  with open(candidate, 'rb') as source:
                    with gzip.GzipFile(fileobj=self.gzipped_file) as target:
                      shutil.copyfileobj(source, target)
                  self.gzipped_file.close()
                return self.gzipped_file.name
              return candidate
          else:
            self.send_response(404)
            return None
      self.send_response(404)
      return None

    def guess_type(self, path):
      # This is needed so that exploded Sky apps without shebang can still run
      # thanks to content-type mappings.
      # TODO(ppi): drop this part once we can rely on the Sky files declaring
      # correct shebang.
      actual_path = self.original_file_name or path

      if actual_path.endswith('.dart'):
        return 'application/dart'
      return SimpleHTTPServer.SimpleHTTPRequestHandler.guess_type(self,
                                                                  actual_path)

    def log_message(self, *_):
      """Override the base class method to disable logging."""
      pass

    def __del__(self):
      if self.gzipped_file:
        os.remove(self.gzipped_file.name)

  RequestHandler.protocol_version = 'HTTP/1.1'
  return RequestHandler


def start_http_server(mappings, host_port=0):
  """Starts an http server serving files from |local_dir_path| on |host_port|.

  Args:
    mappings: List of tuples (prefix, local_base_path_list) mapping URLs that
        start with |prefix| to one or more local directories enumerated in
        |local_base_path_list|. The prefixes should skip the leading slash.
        The first matching prefix and the first location that contains the
        requested file will be used each time.
    host_port: Port on the host machine to run the server on. Pass 0 to use a
        system-assigned port.

  Returns:
    Tuple of the server address and the port on which it runs.
  """
  assert mappings
  handler_class = _get_handler_class_for_path(mappings)

  try:
    httpd = _SilentTCPServer(('127.0.0.1', host_port), handler_class)
    atexit.register(httpd.shutdown)

    http_thread = threading.Thread(target=httpd.serve_forever)
    http_thread.daemon = True
    http_thread.start()
    return httpd.server_address
  except socket.error as v:
    error_code = v[0]
    print 'Failed to start http server for %s on port %d: %s.' % (
        str(mappings), host_port, os.strerror(error_code))
    if error_code == errno.EADDRINUSE:
      print ('  Run `fuser %d/tcp` to find out which process is using the port;'
             % host_port)
      print ('  or `fuser -k %d/tcp` terminate it.' % host_port)
    print '---'
    raise
