# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Utilities for setting up and tear down WPR and TsProxy service."""

from py_utils import ts_proxy_server
from py_utils import webpagereplay_go_server

from devil.android import forwarder

PROXY_HOST_IP = '127.0.0.1'
# From Catapult/WebPageReplay document.
IGNORE_CERT_ERROR_SPKI_LIST = 'PhrPvGIaAMmd29hj8BCZOq096yj7uMpRNHpn5PDxI6I='
PROXY_SERVER = 'socks5://localhost'
DEFAULT_DEVICE_PORT = 1080
DEFAULT_ROUND_TRIP_LATENCY_MS = 100
DEFAULT_DOWNLOAD_BANDWIDTH_KBPS = 72000
DEFAULT_UPLOAD_BANDWIDTH_KBPS = 72000


class WPRServer:
  """Utils to set up a webpagereplay_go_server instance."""

  def __init__(self):
    self._archive_path = None
    self._host_http_port = 0
    self._host_https_port = 0
    self._record_mode = False
    self._server = None

  def StartServer(self, wpr_archive_path):
    """Starts a webpagereplay_go_server instance."""
    if wpr_archive_path == self._archive_path and self._server:
      # Reuse existing webpagereplay_go_server instance.
      return

    if self._server:
      self.StopServer()

    replay_options = []
    if self._record_mode:
      replay_options.append('--record')

    ports = {}
    if not self._server:
      self._server = webpagereplay_go_server.ReplayServer(
          wpr_archive_path,
          PROXY_HOST_IP,
          http_port=self._host_http_port,
          https_port=self._host_https_port,
          replay_options=replay_options)
      self._archive_path = wpr_archive_path
      ports = self._server.StartServer()

    self._host_http_port = ports['http']
    self._host_https_port = ports['https']

  def StopServer(self):
    """Stops the webpagereplay_go_server instance and resets archive."""
    self._server.StopServer()
    self._server = None
    self._host_http_port = 0
    self._host_https_port = 0

  @staticmethod
  def SetServerBinaryPath(go_binary_path):
    """Sets the go_binary_path for webpagereplay_go_server.ReplayServer."""
    webpagereplay_go_server.ReplayServer.SetGoBinaryPath(go_binary_path)

  @property
  def record_mode(self):
    return self._record_mode

  @record_mode.setter
  def record_mode(self, value):
    self._record_mode = value

  @property
  def http_port(self):
    return self._host_http_port

  @property
  def https_port(self):
    return self._host_https_port

  @property
  def archive_path(self):
    return self._archive_path


class ChromeProxySession:
  """Utils to help set up a Chrome Proxy."""

  def __init__(self, device_proxy_port=DEFAULT_DEVICE_PORT):
    self._device_proxy_port = device_proxy_port
    self._ts_proxy_server = ts_proxy_server.TsProxyServer(PROXY_HOST_IP)
    self._wpr_server = WPRServer()

  @property
  def wpr_record_mode(self):
    """Returns whether this proxy session was running in record mode."""
    return self._wpr_server.record_mode

  @wpr_record_mode.setter
  def wpr_record_mode(self, value):
    self._wpr_server.record_mode = value

  @property
  def wpr_replay_mode(self):
    """Returns whether this proxy session was running in replay mode."""
    return not self._wpr_server.record_mode

  @property
  def wpr_archive_path(self):
    """Returns the wpr archive file path used in this proxy session."""
    return self._wpr_server.archive_path

  @property
  def device_proxy_port(self):
    return self._device_proxy_port

  def GetFlags(self):
    """Gets the chrome command line flags to be needed by ChromeProxySession."""
    extra_flags = []

    extra_flags.append('--ignore-certificate-errors-spki-list=%s' %
                       IGNORE_CERT_ERROR_SPKI_LIST)
    extra_flags.append('--proxy-server=%s:%s' %
                       (PROXY_SERVER, self._device_proxy_port))
    return extra_flags

  @staticmethod
  def SetWPRServerBinary(go_binary_path):
    """Sets the WPR server go_binary_path."""
    WPRServer.SetServerBinaryPath(go_binary_path)

  def Start(self, device, wpr_archive_path):
    """Starts the wpr_server as well as the ts_proxy server and setups env.

    Args:
      device: A DeviceUtils instance.
      wpr_archive_path: A abs path to the wpr archive file.

    """
    self._wpr_server.StartServer(wpr_archive_path)
    self._ts_proxy_server.StartServer()

    # Maps device port to host port
    forwarder.Forwarder.Map(
        [(self._device_proxy_port, self._ts_proxy_server.port)], device)
    # Maps tsProxy port to wpr http/https ports
    self._ts_proxy_server.UpdateOutboundPorts(
        http_port=self._wpr_server.http_port,
        https_port=self._wpr_server.https_port)
    self._ts_proxy_server.UpdateTrafficSettings(
        round_trip_latency_ms=DEFAULT_ROUND_TRIP_LATENCY_MS,
        download_bandwidth_kbps=DEFAULT_DOWNLOAD_BANDWIDTH_KBPS,
        upload_bandwidth_kbps=DEFAULT_UPLOAD_BANDWIDTH_KBPS)

  def Stop(self, device):
    """Stops the wpr_server, and ts_proxy server and tears down env.

    Note that Stop does not reset wpr_record_mode, wpr_replay_mode,
    wpr_archive_path property.

    Args:
      device: A DeviceUtils instance.
    """
    self._wpr_server.StopServer()
    self._ts_proxy_server.StopServer()
    forwarder.Forwarder.UnmapDevicePort(self._device_proxy_port, device)
