#!/usr/bin/env python3

# Copyright (C) 2017 Apple Incorporated. 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER 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 argparse
import subprocess
import sys

from webkitpy.common.host import Host
from webkitpy.layout_tests.controllers.layout_test_finder_legacy import LayoutTestFinder
from webkitpy.layout_tests.servers.run_webkit_httpd import run_server as run_webkit_httpd
from webkitpy.layout_tests.servers.run_webkit_httpd import parse_args as parse_httpd_args

def parse_args(args):
    description = """Open a layout test using the default browser. Script will make sure to start a server if test needs it."""
    parser = argparse.ArgumentParser(prog='open-layout-test', description=description, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('test_name', nargs=1, help='test to open')

    options, args = parser.parse_known_args(args)
    return options, args


def main(argv, stdout, stderr):
    options, args  = parse_args(argv)
    test_name = options.test_name[0]

    host = Host()
    port = host.port_factory.get(None, {})
    driver = port.create_driver(0)
    finder = LayoutTestFinder(port, {})

    paths, tests = finder.find_tests(None, [test_name])
    test_files = [test.test_path for test in tests]
    test_name = paths[0]

    needs_server = False
    if driver.is_http_test(test_name) and not port.is_http_server_running():
        needs_server = not port.is_http_server_running()
    elif driver.is_web_platform_test(test_name) or driver.is_webkit_specific_web_platform_test(test_name):
        needs_server = not port.is_wpt_server_running()

    test_url = driver.test_to_uri(test_name)
    if not needs_server:
        print("Opening %s" % test_url)
        subprocess.Popen(['open', test_url])
        return

    httpd_options, httpd_args = parse_httpd_args(['-u', test_url])
    run_webkit_httpd(httpd_options, httpd_args, stdout, stderr)


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:], sys.stdout, sys.stderr))
