# Copyright (C) 2018 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import logging
import os
import select
import socket
import subprocess
import sys
import threading

from blinkpy.common import exit_codes
from blinkpy.common.path_finder import WEB_TESTS_LAST_COMPONENT
from blinkpy.common.path_finder import get_chromium_src_dir
from blinkpy.web_tests.port import base
from blinkpy.web_tests.port import driver
from blinkpy.web_tests.port import factory
from blinkpy.web_tests.port import linux
from blinkpy.web_tests.port import server_process

# Modules loaded dynamically in _import_fuchsia_runner().
# pylint: disable=invalid-name
fuchsia_target = None
qemu_target = None
symbolizer = None

# pylint: enable=invalid-name


# Imports Fuchsia runner modules. This is done dynamically only when FuchsiaPort
# is instantiated to avoid dependency on Fuchsia runner on other platforms.
def _import_fuchsia_runner():
    sys.path.insert(0, os.path.join(get_chromium_src_dir(), 'build/fuchsia'))

    # pylint: disable=import-error
    # pylint: disable=invalid-name
    # pylint: disable=redefined-outer-name
    global aemu_target
    import aemu_target
    global device_target
    import device_target
    global fuchsia_target
    import target as fuchsia_target
    global qemu_target
    import qemu_target
    global symbolizer
    import symbolizer
    # pylint: enable=import-error
    # pylint: enable=invalid-name
    # pylint: disable=redefined-outer-name


# Path to the content shell package relative to the build directory.
CONTENT_SHELL_PACKAGE_PATH = 'gen/content/shell/content_shell/content_shell.far'

# HTTP path prefixes for the HTTP server.
# WEB_TEST_PATH_PREFIX should be matched to the local directory name of
# web_tests because some tests and test_runner find test root directory
# with it.
WEB_TESTS_PATH_PREFIX = '/third_party/blink/' + WEB_TESTS_LAST_COMPONENT

# Paths to the directory where the fonts are copied to. Must match the path in
# content/shell/app/blink_test_platform_support_fuchsia.cc .
FONTS_DEVICE_PATH = '/system/fonts'

# Number of CPU cores in qemu.
CPU_CORES = 4

# Number of content_shell instances to run in parallel. 1 per CPU core.
MAX_WORKERS = CPU_CORES

PROCESS_START_TIMEOUT = 20

_log = logging.getLogger(__name__)


def _subprocess_log_thread(pipe, prefix):
    try:
        while True:
            line = pipe.readline()
            if not line:
                return
            _log.error('%s: %s', prefix, line)
    finally:
        pipe.close()


class SubprocessOutputLogger(object):
    def __init__(self, process, prefix):
        self._process = process
        self._thread = threading.Thread(
            target=_subprocess_log_thread, args=(process.stdout, prefix))
        self._thread.daemon = True
        self._thread.start()

    def __del__(self):
        self.close()

    def close(self):
        self._process.kill()


class _TargetHost(object):
    def __init__(self, build_path, build_ids_path, ports_to_forward, target,
                 results_directory):
        try:
            self._amber_repo = None
            self._target = target
            self._target.Start()
            self._setup_target(build_path, build_ids_path, ports_to_forward,
                               results_directory)
        except:
            self.cleanup()
            raise

    def _setup_target(self, build_path, build_ids_path, ports_to_forward,
                      results_directory):
        # Tell SSH to forward all server ports from the Fuchsia device to
        # the host.
        forwarding_flags = [
            '-O',
            'forward',  # Send SSH mux control signal.
            '-N',  # Don't execute command
            '-T'  # Don't allocate terminal.
        ]
        for port in ports_to_forward:
            forwarding_flags += ['-R', '%d:localhost:%d' % (port, port)]
        self._proxy = self._target.RunCommandPiped([],
                                                   ssh_args=forwarding_flags,
                                                   stdout=subprocess.PIPE,
                                                   stderr=subprocess.STDOUT)

        self._listener = self._target.RunCommandPiped(['log_listener'],
                                                      stdout=subprocess.PIPE,
                                                      stderr=subprocess.STDOUT)

        listener_log_path = os.path.join(results_directory, 'system_log')
        listener_log = open(listener_log_path, 'w')
        self.symbolizer = symbolizer.RunSymbolizer(
            self._listener.stdout, listener_log, [build_ids_path])

        self._amber_repo = self._target.GetAmberRepo()
        self._amber_repo.__enter__()

        package_path = os.path.join(build_path, CONTENT_SHELL_PACKAGE_PATH)
        self._target.InstallPackage([package_path])

        # Process will be forked for each worker, which may make QemuTarget
        # unusable (e.g. waitpid() for qemu process returns ECHILD after
        # fork() ). Save command runner before fork()ing, to use it later to
        # connect to the target.
        self.target_command_runner = self._target.GetCommandRunner()

    def run_command(self, command):
        return self.target_command_runner.RunCommandPiped(
            command,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)

    def cleanup(self):
        if self._amber_repo:
            self._amber_repo.__exit__(None, None, None)
        if self._target:
            # Emulator targets will be shutdown during cleanup.
            # TODO(sergeyu): Currently __init__() always starts Qemu, so we can
            # just shutdown it. Update this logic when reusing target devices
            # for multiple test runs.
            if not isinstance(self._target, device_target.DeviceTarget):
                self._target.Shutdown()
            self._target = None


class FuchsiaPort(base.Port):
    port_name = 'fuchsia'

    SUPPORTED_VERSIONS = ('fuchsia', )

    FALLBACK_PATHS = {
        'fuchsia':
        ['fuchsia'] + linux.LinuxPort.latest_platform_fallback_path()
    }

    def __init__(self, host, port_name, **kwargs):
        super(FuchsiaPort, self).__init__(host, port_name, **kwargs)

        self._operating_system = 'fuchsia'
        self._version = 'fuchsia'
        self._target_device = self.get_option('device')

        # TODO(sergeyu): Add support for arm64.
        self._architecture = 'x86_64'

        self.server_process_constructor = FuchsiaServerProcess

        # Used to implement methods that depend on the host platform.
        self._host_port = factory.PortFactory(host).get(**kwargs)

        self._target_host = self.get_option('fuchsia_target')
        self._zircon_logger = None
        self._host_ip = self.get_option('fuchsia_host_ip')
        _import_fuchsia_runner()

    def _driver_class(self):
        return ChromiumFuchsiaDriver

    def _path_to_driver(self, target=None):
        return self._build_path_with_target(target, CONTENT_SHELL_PACKAGE_PATH)

    def __del__(self):
        if self._zircon_logger:
            self._zircon_logger.close()

    def setup_test_run(self):
        super(FuchsiaPort, self).setup_test_run()
        try:
            target_args = {
                'out_dir': self._build_path(),
                'system_log_file': None,
                'fuchsia_out_dir': self.get_option('fuchsia_out_dir')
            }
            if self._target_device == 'device':
                additional_args = {
                    'target_cpu': self.get_option('fuchsia_target_cpu'),
                    'ssh_config': self.get_option('fuchsia_ssh_config'),
                    'os_check': 'ignore',
                    'host': self.get_option('fuchsia_host'),
                    'port': self.get_option('fuchsia_port'),
                    'node_name': self.get_option('fuchsia_node_name')
                }
                target_args.update(additional_args)
                target = device_target.DeviceTarget(**target_args)
            else:
                additional_args = {
                    'target_cpu': 'x64',
                    'cpu_cores': CPU_CORES,
                    'require_kvm': True,
                    'ram_size_mb': 8192
                }
                if self._target_device == 'qemu':
                    target_args.update(additional_args)
                    target = qemu_target.QemuTarget(**target_args)
                else:
                    additional_args.update({
                        'enable_graphics': False,
                        'hardware_gpu': False
                    })
                    target_args.update(additional_args)
                    target = aemu_target.AemuTarget(**target_args)
            self._target_host = _TargetHost(self._build_path(),
                                            self.get_build_ids_path(),
                                            self.SERVER_PORTS, target,
                                            self.results_directory())

            if self.get_option('zircon_logging'):
                self._zircon_logger = SubprocessOutputLogger(
                    self._target_host.run_command(['dlog', '-f']), 'Zircon')

            # Save fuchsia_target in _options, so it can be shared with other
            # workers.
            self._options.fuchsia_target = self._target_host

        except fuchsia_target.FuchsiaTargetException as e:
            _log.error('Failed to start qemu: %s.', str(e))
            return exit_codes.NO_DEVICES_EXIT_STATUS

    def clean_up_test_run(self):
        if self._target_host:
            self._target_host.cleanup()
            self._target_host = None

    def num_workers(self, requested_num_workers):
        # Run a single qemu instance.
        return min(MAX_WORKERS, requested_num_workers)

    def _default_timeout_ms(self):
        # Use 20s timeout instead of the default 6s. This is necessary because
        # the tests are executed in qemu, so they run slower compared to other
        # platforms.
        return 20000

    def requires_http_server(self):
        """HTTP server is always required to avoid copying the tests to the VM.
        """
        return True

    def start_http_server(self, additional_dirs, number_of_drivers):
        additional_dirs['/third_party/blink/PerformanceTests'] = \
            self._perf_tests_dir()
        additional_dirs[WEB_TESTS_PATH_PREFIX] = self.web_tests_dir()
        additional_dirs['/gen'] = self.generated_sources_directory()
        additional_dirs['/third_party/blink'] = \
            self._path_from_chromium_base('third_party', 'blink')
        super(FuchsiaPort, self).start_http_server(additional_dirs,
                                                   number_of_drivers)

    def path_to_apache(self):
        return self._host_port.path_to_apache()

    def path_to_apache_config_file(self):
        return self._host_port.path_to_apache_config_file()

    def default_smoke_test_only(self):
        return True

    def get_target_host(self):
        return self._target_host

    def get_build_ids_path(self):
        package_path = self._path_to_driver()
        return os.path.join(os.path.dirname(package_path), 'ids.txt')


class ChromiumFuchsiaDriver(driver.Driver):
    def __init__(self, port, worker_number, no_timeout=False):
        super(ChromiumFuchsiaDriver, self).__init__(port, worker_number,
                                                    no_timeout)

    def _initialize_server_process(self, server_name, cmd_line, environment):
        self._server_process = self._port.server_process_constructor(
            self._port,
            server_name,
            cmd_line,
            environment,
            more_logging=self._port.get_option('driver_logging'),
            host_ip=self._port._host_ip)

    def _base_cmd_line(self):
        cmd = [
            'run',
            'fuchsia-pkg://fuchsia.com/content_shell#meta/content_shell.cmx'
        ]
        if self._port._target_device == 'qemu':
            cmd.append('--ozone-platform=headless')
        # Use Scenic on AEMU
        else:
            cmd.extend([
                '--ozone-platform=scenic', '--enable-oop-rasterization',
                '--use-vulkan', '--enable-gpu-rasterization',
                '--force-device-scale-factor=1', '--use-gl=stub',
                '--enable-features=UseSkiaRenderer,Vulkan'
            ])
        return cmd

    def _command_from_driver_input(self, driver_input):
        command = super(ChromiumFuchsiaDriver,
                        self)._command_from_driver_input(driver_input)
        if command.startswith('/'):
            relative_test_filename = \
                os.path.relpath(command, self._port.web_tests_dir())
            command = 'http://127.0.0.1:8000' + WEB_TESTS_PATH_PREFIX + \
                '/' + relative_test_filename
        return command


# Custom version of ServerProcess that runs processes on a remote device.
class FuchsiaServerProcess(server_process.ServerProcess):
    def __init__(self,
                 port_obj,
                 name,
                 cmd,
                 env=None,
                 treat_no_data_as_crash=False,
                 more_logging=False,
                 host_ip=None):
        super(FuchsiaServerProcess, self).__init__(
            port_obj, name, cmd, env, treat_no_data_as_crash, more_logging)
        self._symbolizer_proc = None
        self._host_ip = host_ip or qemu_target.HOST_IP_ADDRESS

    def _start(self):
        if self._proc:
            raise ValueError('%s already running' % self._name)
        self._reset()

        # Fuchsia doesn't support stdin stream for packaged applications, so the
        # stdin stream for content_shell is routed through a separate TCP
        # socket. Open a local socket and then pass the address with the port as
        # --stdin-redirect parameter. content_shell will connect to this address
        # and will use that connection as its stdin stream.
        listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        listen_socket.bind(('127.0.0.1', 0))
        listen_socket.listen(1)
        stdin_port = listen_socket.getsockname()[1]

        command = ['%s=%s' % (k, v) for k, v in self._env.items()] + \
            self._cmd + \
            ['--no-sandbox', '--stdin-redirect=%s:%s' %
             (self._host_ip, stdin_port)]
        proc = self._port.get_target_host().run_command(command)
        # Wait for incoming connection from content_shell.
        fd = listen_socket.fileno()
        read_fds, _, _ = select.select([fd], [], [], PROCESS_START_TIMEOUT)
        if fd not in read_fds:
            listen_socket.close()
            proc.kill()
            raise driver.DeviceFailure(
                'Timed out waiting connection from content_shell.')

        # Python's interfaces for sockets and pipes are different. To masquerade
        # the socket as a pipe dup() the file descriptor and pass it to
        # os.fdopen().
        stdin_socket, _ = listen_socket.accept()
        fd = stdin_socket.fileno()  # pylint: disable=no-member
        stdin_pipe = os.fdopen(os.dup(fd), "w", 0)
        stdin_socket.close()

        proc.stdin.close()
        proc.stdin = stdin_pipe
        # Run symbolizer to filter the stderr stream.
        self._symbolizer_proc = symbolizer.RunSymbolizer(
            proc.stderr, subprocess.PIPE, [self._port.get_build_ids_path()])
        proc.stderr = self._symbolizer_proc.stdout

        self._set_proc(proc)

    def stop(self, timeout_secs=0.0, kill_tree=False):
        result = super(FuchsiaServerProcess, self).stop(
            timeout_secs, kill_tree)
        if self._symbolizer_proc:
            self._symbolizer_proc.kill()
        return result
