# Copyright (C) 2010 Google Inc. All rights reserved.
# Copyright (C) 2013-2018 Apple Inc. All rights reserved.
# Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
#
# 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.

"""Factory method to retrieve the appropriate port implementation."""

import fnmatch
import optparse
import re

from webkitpy.port import builders
from webkitpy.port import config
from webkitpy.common.system import executive
from webkitpy.common.system import filesystem


def platform_options(use_globs=False):
    return [
        optparse.make_option('--platform', action='store',
            help=('Glob-style list of platform/ports to use (e.g., "mac*")' if use_globs else 'Platform to use (e.g., "mac-lion")')),
        optparse.make_option('--ios-simulator', action='store_const', dest='platform',
            const=('ios-simulator'),
            help=('Alias for --platform=ios-simulator')),
        optparse.make_option('--iphone-simulator', action='store_const', dest='platform',
            const=('iphone-simulator'),
            help=('Alias for --platform=iphone-simulator')),
        optparse.make_option('--ipad-simulator', action='store_const', dest='platform',
            const=('ipad-simulator'),
            help=('Alias for --platform=ipad-simulator')),
        optparse.make_option('--simulator', action='store_const', dest='platform',
            const=('ios-simulator'),
            help=('DEPRECATED alias for --platform=ios-simulator')),
        optparse.make_option('--gtk', action='store_const', dest='platform',
            const=('gtk*' if use_globs else 'gtk'),
            help=('Alias for --platform=gtk*' if use_globs else 'Alias for --platform=gtk')),
        optparse.make_option('--wpe', action='store_const', dest='platform',
            const=('wpe*' if use_globs else 'wpe'),
            help=('Alias for --platform=wpe')),
        optparse.make_option('--wincairo', action='store_const', dest='platform',
            const=('wincairo'),
            help=('Alias for --platform=wincairo')),
        ] + (config.apple_additions().platform_options() if config.apple_additions() else [])


def configuration_options():
    return [
        optparse.make_option("-t", "--target", default=config.Config(executive.Executive(), filesystem.FileSystem()).default_configuration(), dest="configuration", help="(DEPRECATED) (default: %default)"),
        optparse.make_option('--debug', action='store_const', const='Debug', dest="configuration",
            help='Set the configuration to Debug'),
        optparse.make_option('--release', action='store_const', const='Release', dest="configuration",
            help='Set the configuration to Release'),
        optparse.make_option('--64-bit', action='store_const', const='x86_64', default=None, dest="architecture",
            help='use 64-bit binaries by default (x86_64 instead of x86)'),
        optparse.make_option('--32-bit', action='store_const', const='x86', default=None, dest="architecture",
            help='use 32-bit binaries by default (x86 instead of x86_64)'),
        ]


def _builder_options(builder_name):
    configuration = "Debug" if re.search(r"[d|D](ebu|b)g", builder_name) else "Release"
    is_webkit2 = builder_name.find("WK2") != -1
    builder_name = builder_name
    return optparse.Values({'builder_name': builder_name, 'configuration': configuration, 'webkit_test_runner': is_webkit2})


class PortFactory(object):
    # Order matters.  For port classes that have a port_name with a
    # common prefix, the more specific port class should be listed
    # first.
    PORT_CLASSES = (
        'gtk.GtkPort',
        'ios_simulator.IOSSimulatorPort',
        'ios_simulator.IPhoneSimulatorPort',
        'ios_simulator.IPadSimulatorPort',
        'ios_device.IOSDevicePort',
        'watch_simulator.WatchSimulatorPort',
        'watch_device.WatchDevicePort',
        'jsc_only.JscOnlyPort',
        'mac.MacPort',
        'mock_drt.MockDRTPort',
        'test.TestPort',
        'win.WinCairoPort',
        'win.WinPort',
        'wpe.WPEPort',
    )

    def __init__(self, host):
        self._host = host

    def _default_port(self, options):
        platform = self._host.platform
        if platform.is_linux() or platform.is_freebsd():
            return 'gtk'
        elif platform.is_mac():
            return 'mac'
        elif platform.is_win():
            return 'win'
        raise NotImplementedError('unknown platform: %s' % platform)

    def get(self, port_name=None, options=None, **kwargs):
        """Returns an object implementing the Port interface. If
        port_name is None, this routine attempts to guess at the most
        appropriate port on this platform."""
        port_name = port_name or self._default_port(options)

        classes = []
        for port_class in self.PORT_CLASSES:
            module_name, class_name = port_class.rsplit('.', 1)
            module = __import__(module_name, globals(), locals(), [], -1)
            cls = module.__dict__[class_name]
            classes.append(cls)
        if config.apple_additions() and hasattr(config.apple_additions(), 'ports'):
            classes += config.apple_additions().ports()

        for cls in classes:
            if port_name.startswith(cls.port_name):
                port_name = cls.determine_full_port_name(self._host, options, port_name)
                return cls(self._host, port_name, options=options, **kwargs)
        raise NotImplementedError('unsupported platform: "%s"' % port_name)

    def all_port_names(self, platform=None):
        """Return a list of all valid, fully-specified, "real" port names.

        This is the list of directories that are used as actual baseline_paths()
        by real ports. This does not include any "fake" names like "test"
        or "mock-mac", and it does not include any directories that are not.

        If platform is not specified, we will glob-match all ports"""
        platform = platform or '*'
        return fnmatch.filter(builders.all_port_names(), platform)

    def get_from_builder_name(self, builder_name):
        port_name = builders.port_name_for_builder_name(builder_name)
        assert port_name, "unrecognized builder name '%s'" % builder_name
        return self.get(port_name, _builder_options(builder_name))
