# Copyright 2014 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 json
import logging
import os
import os.path
import random
import subprocess
import sys
import threading
import time

import SimpleHTTPServer
import SocketServer

from mopy.config import Config
from mopy.paths import Paths

sys.path.insert(0, os.path.join(Paths().src_root, 'build', 'android'))
from pylib import android_commands
from pylib import constants


# Tags used by the mojo shell application logs.
LOGCAT_TAGS = [
    'AndroidHandler',
    'MojoFileHelper',
    'MojoMain',
    'MojoShellActivity',
    'MojoShellApplication',
    'chromium',
]

MOJO_SHELL_PACKAGE_NAME = 'org.chromium.mojo.shell'


class Context(object):
  """
  The context object allowing to run multiple runs of the shell.
  """
  def __init__(self, device, device_port):
    self.device = device
    self.device_port = device_port


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.
  """
  def handle_error(self, request, client_address):
    """
    Override the base class method to have conditional logging.
    """
    if logging.getLogger().isEnabledFor(logging.DEBUG):
      super(_SilentTCPServer, self).handle_error(request, client_address)


def _GetHandlerClassForPath(base_path):
  class RequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    """
    Handler for SocketServer.TCPServer that will serve the files from
    |base_path| directory over http.
    """

    def translate_path(self, path):
      path_from_current = (
          SimpleHTTPServer.SimpleHTTPRequestHandler.translate_path(self, path))
      return os.path.join(base_path, os.path.relpath(path_from_current))

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

  return RequestHandler


def _ExitIfNeeded(process):
  """
  Exits |process| if it is still alive.
  """
  if process.poll() is None:
    process.kill()


def _ReadFifo(context, fifo_path, pipe, on_fifo_closed, max_attempts=5):
  """
  Reads |fifo_path| on the device and write the contents to |pipe|. Calls
  |on_fifo_closed| when the fifo is closed. This method will try to find the
  path up to |max_attempts|, waiting 1 second between each attempt. If it cannot
  find |fifo_path|, a exception will be raised.
  """
  def Run():
    def _WaitForFifo():
      for _ in xrange(max_attempts):
        if context.device.FileExistsOnDevice(fifo_path):
          return
        time.sleep(1)
      if on_fifo_closed:
        on_fifo_closed()
      raise Exception("Unable to find fifo.")
    _WaitForFifo()
    stdout_cat = subprocess.Popen([constants.GetAdbPath(),
                                   'shell',
                                   'cat',
                                   fifo_path],
                                  stdout=pipe)
    atexit.register(_ExitIfNeeded, stdout_cat)
    stdout_cat.wait()
    if on_fifo_closed:
      on_fifo_closed()

  thread = threading.Thread(target=Run, name="StdoutRedirector")
  thread.start()


def _MapPort(device, device_port, host_port):
  """
  Maps the device port to the host port. If |device_port| is 0, a random
  available port is chosen. Returns the device port.
  """
  def _FindAvailablePortOnDevice(device):
    opened = device.RunShellCommand('netstat')
    opened = [int(x.strip().split()[3].split(':')[1])
              for x in opened if x.startswith(' tcp')]
    while True:
      port = random.randint(4096, 16384)
      if port not in opened:
        return port
  if device_port == 0:
    device_port = _FindAvailablePortOnDevice(device)
  adb_path = constants.GetAdbPath()
  subprocess.Popen([adb_path,
                    "reverse",
                    "tcp:%d" % device_port,
                    "tcp:%d" % host_port]).wait()
  def _UnmapPort():
    subprocess.Popen([adb_path, "reverse", "--remove",  "tcp:%d" % device_port])
  atexit.register(_UnmapPort)
  return device_port


def PrepareShellRun(config):
  """
  Returns a context allowing a shell to be run.

  This will start an internal http server to serve mojo applications, forward a
  local port on the device to this http server and install the current version
  of the mojo shell.
  """
  build_dir = Paths(config).build_dir
  constants.SetOutputDirectort(build_dir)

  httpd = _SilentTCPServer(('127.0.0.1', 0), _GetHandlerClassForPath(build_dir))
  atexit.register(httpd.shutdown)
  host_port = httpd.server_address[1]

  http_thread = threading.Thread(target=httpd.serve_forever)
  http_thread.daemon = True
  http_thread.start()

  device = android_commands.AndroidCommands(
      android_commands.GetAttachedDevices()[0])
  device.EnableAdbRoot()

  device.ManagedInstall(os.path.join(build_dir, 'apks', 'MojoShell.apk'),
                        keep_data=True,
                        package_name=MOJO_SHELL_PACKAGE_NAME)

  context = Context(device, _MapPort(device, 0, host_port))

  atexit.register(StopShell, context)
  return context


def StartShell(context, arguments, stdout=None, on_application_stop=None):
  """
  Starts the mojo shell, passing it the given arguments.

  If stdout is not None, it should be a valid argument for subprocess.Popen.
  """
  STDOUT_PIPE = "/data/data/%s/stdout.fifo" % MOJO_SHELL_PACKAGE_NAME

  cmd = [constants.GetAdbPath(),
         'shell',
         'am',
         'start',
         '-W',
         '-S',
         '-a', 'android.intent.action.VIEW',
         '-n', '%s/.MojoShellActivity' % MOJO_SHELL_PACKAGE_NAME]

  parameters = ['--origin=http://127.0.0.1:%d/' % context.device_port]
  if stdout or on_application_stop:
    context.device.RunShellCommand('rm %s' % STDOUT_PIPE)
    parameters.append('--fifo-path=%s' % STDOUT_PIPE)
    _ReadFifo(context, STDOUT_PIPE, stdout, on_application_stop)
  parameters += arguments

  if parameters:
    encodedParameters = json.dumps(parameters)
    cmd += [ '--es', 'encodedParameters', encodedParameters]

  with open(os.devnull, 'w') as devnull:
    subprocess.Popen(cmd, stdout=devnull).wait()


def StopShell(context):
  """
  Stops the mojo shell.
  """
  context.device.RunShellCommand('am force-stop %s' % MOJO_SHELL_PACKAGE_NAME)

def CleanLogs(context):
  """
  Cleans the logs on the device.
  """
  context.device.RunShellCommand('logcat -c')


def ShowLogs():
  """
  Displays the log for the mojo shell.

  Returns the process responsible for reading the logs.
  """
  logcat = subprocess.Popen([constants.GetAdbPath(),
                             'logcat',
                             '-s',
                             ' '.join(LOGCAT_TAGS)],
                            stdout=sys.stdout)
  atexit.register(_ExitIfNeeded, logcat)
  return logcat


def GetFilePath(filename):
  """
  Returns a path suitable for the application to create a file.
  """
  return '/data/data/%s/files/%s' % (MOJO_SHELL_PACKAGE_NAME, filename)
