#  Copyright (c) 2014, Canon 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:
#  1.  Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#  2.  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.
#  3.  Neither the name of Canon 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 CANON INC. AND ITS 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 CANON INC. AND ITS 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 json
import logging
import sys
import time

from webkitpy.layout_tests.servers import http_server_base

_log = logging.getLogger(__name__)


def doc_root(port_obj):
    doc_root = port_obj.get_option("wptserver_doc_root")
    if doc_root is None:
        return port_obj.host.filesystem.join("imported", "w3c", "web-platform-tests")
    return doc_root


def wpt_config_json(port_obj):
    config_wk_filepath = port_obj._filesystem.join(port_obj.layout_tests_dir(), "imported", "w3c", "resources", "config.json")
    if not port_obj.host.filesystem.isfile(config_wk_filepath):
        return
    json_data = port_obj._filesystem.read_text_file(config_wk_filepath)
    return json.loads(json_data)


def base_http_url(port_obj):
    config = wpt_config_json(port_obj)
    if not config:
        # This should only be hit by webkitpy unit tests
        _log.debug("No WPT config file found")
        return "http://localhost:8800/"
    ports = config["ports"]
    return "http://" + config["browser_host"] + ":" + str(ports["http"][0]) + "/"


def base_https_url(port_obj):
    config = wpt_config_json(port_obj)
    if not config:
        # This should only be hit by webkitpy unit tests
        _log.debug("No WPT config file found")
        return "https://localhost:9443/"
    ports = config["ports"]
    return "https://" + config["browser_host"] + ":" + str(ports["https"][0]) + "/"


def is_wpt_server_running(port_obj):
    config = wpt_config_json(port_obj)
    if not config:
        return False
    return http_server_base.HttpServerBase._is_running_on_port(config["ports"]["http"][0])


class WebPlatformTestServer(http_server_base.HttpServerBase):
    def __init__(self, port_obj, name, pidfile=None):
        http_server_base.HttpServerBase.__init__(self, port_obj)
        self._output_dir = port_obj.results_directory()

        self._name = name
        self._log_file_name = '%s_process_log.out.txt' % (self._name)

        self._output_log_path = None
        self._wsout = None
        self._process = None
        self._pid_file = pidfile
        if not self._pid_file:
            self._pid_file = self._filesystem.join(self._runtime_path, '%s.pid' % self._name)

        self._filesystem = port_obj.host.filesystem
        self._layout_root = port_obj.layout_tests_dir()
        self._doc_root = self._filesystem.join(self._layout_root, doc_root(port_obj))

        self._doc_root_path = self._filesystem.join(self._layout_root, self._doc_root)
        self._config_filename = self._filesystem.join(self._doc_root_path, "config.json")

        # FIXME https://webkit.org/b/222703
        python_interp = sys.executable
        if sys.version_info < (3, 0):
            python_interp = 'python3'

        wpt_file = self._filesystem.join(self._doc_root_path, "wpt.py")
        self._start_cmd = [python_interp, wpt_file, "serve", "--config", self._config_filename]

        self._mappings = []
        config = wpt_config_json(port_obj)
        if config:
            ports = config["ports"]
            for key in ports:
                for value in ports[key]:
                    port = {"port": value}
                    if key == "https":
                        port["sslcert"] = True
                    self._mappings.append(port)

    def ports_to_forward(self):
        return [mapping['port'] for mapping in self._mappings]

    def _prepare_config(self):
        self._filesystem.maybe_make_directory(self._output_dir)
        self._output_log_path = self._filesystem.join(self._output_dir, self._log_file_name)
        self._wsout = self._filesystem.open_text_file_for_writing(self._output_log_path)

        _log.debug('Copying WebKit web platform server config.json')
        config_wk_filename = self._filesystem.join(self._layout_root, "imported", "w3c", "resources", "config.json")
        if self._filesystem.isfile(config_wk_filename):
            config = json.loads(self._filesystem.read_text_file(config_wk_filename))
            config['ssl']['openssl']['base_path'] = self._filesystem.join(self._output_dir, "_wpt_certs")
            self._filesystem.write_text_file(self._config_filename, json.dumps(config))

    def _spawn_process(self):
        self._process = self._executive.popen(self._start_cmd, cwd=self._doc_root_path, shell=False, stdin=self._executive.PIPE, stdout=self._wsout, stderr=self._wsout)
        self._filesystem.write_text_file(self._pid_file, str(self._process.pid))

        # Wait a second for the server to actually start so that tests do not start until server is running.
        time.sleep(1)

        # The server is not running after 1 second, something went wrong.
        if self._process.poll() is not None:
            self._stop_running_server()
            error_log = ('WPT Server process exited prematurely with status code %s\n' % self._process.returncode
                         + 'The cmdline for running the WPT server was: %s\n' % self._start_cmd
                         + 'The working dir was: %s\n' % self._doc_root_path)
            if self._output_log_path is not None and self._filesystem.exists(self._output_log_path):
                error_log += 'Check the logfile for the command at: %s\n' % self._output_log_path
            raise http_server_base.ServerError(error_log)

        return self._process.pid

    def _stop_running_server(self):
        _log.debug('Cleaning WPT web platform server config.json')
        if self._filesystem.isfile(self._config_filename):
            self._filesystem.remove(self._config_filename)

        if self._wsout:
            self._wsout.close()
            self._wsout = None

        if self._process is not None:
            self._process.poll()

        if self._pid:
            # kill_process will not kill the subprocesses, interrupt does the job.
            self._executive.interrupt(self._pid)

        self._remove_pid_file()
