# Copyright (C) 2011 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.
"""Represents a set of builder bots running web tests.

This class is used to hold a list of builder bots running web tests and their
corresponding port names and TestExpectations specifiers.
"""

import json

from blinkpy.common.path_finder import PathFinder

class BuilderList(object):
    def __init__(self, builders_dict):
        """Creates and validates a builders list.

        The given dictionary maps builder names to dicts with the keys:
            "port_name": A fully qualified port name.
            "specifiers": A list of specifiers used to describe a builder.
                The specifiers list will at the very least have a valid
                port version specifier like "Mac10.15" and and a valid build
                type specifier like "Release".
            "is_try_builder": Whether the builder is a trybot.
            "master": The master name of the builder. It is deprecated, but still required
                by test-results.appspot.com API."
            "has_webdriver_tests": Whether webdriver_tests_suite runs on this builder.

        Possible refactoring note: Potentially, it might make sense to use
        blinkpy.common.net.results_fetcher.Builder and add port_name and
        specifiers properties to that class.
        """
        self._builders = builders_dict
        for builder in builders_dict:
            specifiers = {
                s.lower() for s in builders_dict[builder].get('specifiers', {})}
            assert 'port_name' in builders_dict[builder]
            assert ('android' in specifiers or
                    len(builders_dict[builder]['specifiers']) == 2)

    @staticmethod
    def load_default_builder_list(filesystem):
        """Loads the set of builders from a JSON file and returns the BuilderList."""
        path = PathFinder(filesystem).path_from_blink_tools(
            'blinkpy', 'common', 'config', 'builders.json')
        contents = filesystem.read_text_file(path)
        return BuilderList(json.loads(contents))

    def all_builder_names(self):
        return sorted(self._builders)

    def all_try_builder_names(self):
        return self.filter_builders(is_try=True)

    def all_cq_try_builder_names(self):
        return self.filter_builders(is_cq=True)

    def all_continuous_builder_names(self):
        return self.filter_builders(is_try=False)

    def filter_builders(self, exclude_specifiers=None, include_specifiers=None,
                        is_try=False, is_cq=False):
        _lower_specifiers = lambda specifiers: {s.lower() for s in specifiers}
        exclude_specifiers = _lower_specifiers(exclude_specifiers or {})
        include_specifiers = _lower_specifiers(include_specifiers or {})
        builders = []
        for b in self._builders:
            builder_specifiers = _lower_specifiers(
                self._builders[b].get('specifiers', {}))
            if is_try and self._builders[b].get('is_try_builder', False) != is_try:
                continue
            if is_cq and self._builders[b].get('is_cq_builder', False) != is_cq:
                continue
            if ((not is_cq and not is_try) and self._builders[b].get('is_try_builder', False)):
                continue
            if builder_specifiers & exclude_specifiers:
                continue
            if  (include_specifiers and
                     not include_specifiers & builder_specifiers):
                continue
            builders.append(b)
        return sorted(builders)

    def all_port_names(self):
        return sorted({b['port_name'] for b in self._builders.values()})

    def bucket_for_builder(self, builder_name):
        return self._builders[builder_name].get('bucket', '')

    def master_for_builder(self, builder_name):
        return self._builders[builder_name].get('master', '')

    def has_webdriver_tests_for_builder(self, builder_name):
        return self._builders[builder_name].get('has_webdriver_tests')

    def port_name_for_builder_name(self, builder_name):
        return self._builders[builder_name]['port_name']

    def specifiers_for_builder(self, builder_name):
        return self._builders[builder_name]['specifiers']

    def is_try_server_builder(self, builder_name):
        return self._builders[builder_name].get('is_try_builder', False)

    def is_wpt_builder(self, builder_name):
        return 'wpt' in builder_name

    def platform_specifier_for_builder(self, builder_name):
        return self.specifiers_for_builder(builder_name)[0]

    def builder_name_for_port_name(self, target_port_name):
        """Returns a builder name for the given port name.

        Multiple builders can have the same port name; this function only
        returns builder names for non-try-bot builders, and it gives preference
        to non-debug builders. If no builder is found, None is returned.
        """
        debug_builder_name = None
        for builder_name, builder_info in self._builders.iteritems():
            if builder_info.get('is_try_builder'):
                continue
            if builder_info['port_name'] == target_port_name:
                if 'dbg' in builder_name:
                    debug_builder_name = builder_name
                else:
                    return builder_name
        return debug_builder_name

    def version_specifier_for_port_name(self, target_port_name):
        """Returns the OS version specifier for a given port name.

        This just uses information in the builder list, and it returns
        the version specifier for the first builder that matches, even
        if it's a try bot builder.
        """
        for _, builder_info in sorted(self._builders.iteritems()):
            if builder_info['port_name'] == target_port_name:
                return builder_info['specifiers'][0]
        return None

    def builder_name_for_specifiers(self, version, build_type, is_try_builder):
        """Returns the builder name for a give version and build type.

        Args:
            version: A string with the OS version specifier. e.g. "Trusty", "Win10".
            build_type: A string with the build type. e.g. "Debug" or "Release".

        Returns:
            The builder name if found, or an empty string if no match was found.
        """
        for builder_name, info in sorted(self._builders.items()):
            specifiers = set(spec.lower() for spec in info['specifiers'])
            is_try_builder_info = info.get('is_try_builder', False)
            if (version.lower() in specifiers
                    and build_type.lower() in specifiers
                    and is_try_builder_info == is_try_builder):
                return builder_name
        return ''
