# Copyright (c) 2010 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.

from __future__ import print_function
import json
import logging
import optparse
import re
import sys
import traceback

from webkitpy.common.memoized import memoized
from webkitpy.common.net.buildbot import Build
from webkitpy.common.system.executive import ScriptError
from webkitpy.layout_tests.models.testharness_results import is_all_pass_testharness_result
from webkitpy.layout_tests.models.test_expectations import TestExpectations, BASELINE_SUFFIX_LIST, SKIP
from webkitpy.layout_tests.port import factory
from webkitpy.tool.commands.command import Command


_log = logging.getLogger(__name__)


class AbstractRebaseliningCommand(Command):
    """Base class for rebaseline-related commands."""
    # Not overriding execute() - pylint: disable=abstract-method

    no_optimize_option = optparse.make_option(
        '--no-optimize', dest='optimize', action='store_false', default=True,
        help=('Do not optimize (de-duplicate) the expectations after rebaselining '
              '(default is to de-dupe automatically). You can use "webkit-patch '
              'optimize-baselines" to optimize separately.'))
    platform_options = factory.platform_options(use_globs=True)
    results_directory_option = optparse.make_option(
        '--results-directory', help='Local results directory to use.')
    suffixes_option = optparse.make_option(
        '--suffixes', default=','.join(BASELINE_SUFFIX_LIST), action='store',
        help='Comma-separated-list of file types to rebaseline.')
    builder_option = optparse.make_option(
        '--builder', help='Builder to pull new baselines from.')
    test_option = optparse.make_option('--test', help='Test to rebaseline.')
    build_number_option = optparse.make_option(
        '--build-number', default=None, type='int',
        help='Optional build number; if not given, the latest build is used.')

    def __init__(self, options=None):
        super(AbstractRebaseliningCommand, self).__init__(options=options)
        self._baseline_suffix_list = BASELINE_SUFFIX_LIST
        self.expectation_line_changes = ChangeSet()
        self._tool = None

    def _print_expectation_line_changes(self):
        print(json.dumps(self.expectation_line_changes.to_dict()))

    def _baseline_directory(self, builder_name):
        port = self._tool.port_factory.get_from_builder_name(builder_name)
        return port.baseline_version_dir()

    def _test_root(self, test_name):
        return self._tool.filesystem.splitext(test_name)[0]

    def _file_name_for_actual_result(self, test_name, suffix):
        return '%s-actual.%s' % (self._test_root(test_name), suffix)

    def _file_name_for_expected_result(self, test_name, suffix):
        return '%s-expected.%s' % (self._test_root(test_name), suffix)


class ChangeSet(object):
    """A record of TestExpectation lines to remove.

    TODO(qyearsley): Remove this class, track list of lines to remove directly
    in an attribute of AbstractRebaseliningCommand.
    """

    def __init__(self, lines_to_remove=None):
        self.lines_to_remove = lines_to_remove or {}

    def remove_line(self, test, builder):
        if test not in self.lines_to_remove:
            self.lines_to_remove[test] = []
        self.lines_to_remove[test].append(builder)

    def to_dict(self):
        remove_lines = []
        for test in self.lines_to_remove:
            for builder in self.lines_to_remove[test]:
                remove_lines.append({'test': test, 'builder': builder})
        return {'remove-lines': remove_lines}

    @staticmethod
    def from_dict(change_dict):
        lines_to_remove = {}
        if 'remove-lines' in change_dict:
            for line_to_remove in change_dict['remove-lines']:
                test = line_to_remove['test']
                builder = line_to_remove['builder']
                if test not in lines_to_remove:
                    lines_to_remove[test] = []
                lines_to_remove[test].append(builder)
        return ChangeSet(lines_to_remove=lines_to_remove)

    def update(self, other):
        assert isinstance(other, ChangeSet)
        assert isinstance(other.lines_to_remove, dict)
        for test in other.lines_to_remove:
            if test not in self.lines_to_remove:
                self.lines_to_remove[test] = []
            self.lines_to_remove[test].extend(other.lines_to_remove[test])


class CopyExistingBaselinesInternal(AbstractRebaseliningCommand):
    name = 'copy-existing-baselines-internal'
    help_text = ('Copy existing baselines down one level in the baseline order to ensure '
                 "new baselines don't break existing passing platforms.")

    def __init__(self):
        super(CopyExistingBaselinesInternal, self).__init__(options=[
            self.results_directory_option,
            self.suffixes_option,
            self.builder_option,
            self.test_option,
        ])

    @memoized
    def _immediate_predecessors_in_fallback(self, path_to_rebaseline):
        """Returns the predecessor directories in the baseline fall-back graph.

        The platform-specific fall-back baseline directories form a tree; the
        "immediate predecessors" are the children nodes For example, if the
        baseline fall-back graph includes:
            "mac10.9" -> "mac10.10/"
            "mac10.10/" -> "mac/"
            "retina/" -> "mac/"
        Then, the "immediate predecessors" are:
            "mac/": ["mac10.10/", "retina/"]
            "mac10.10/": ["mac10.9/"]
            "mac10.9/", "retina/": []
        """
        port_names = self._tool.port_factory.all_port_names()
        immediate_predecessors = []
        for port_name in port_names:
            port = self._tool.port_factory.get(port_name)
            baseline_search_path = port.baseline_search_path()
            try:
                index = baseline_search_path.index(path_to_rebaseline)
                if index:
                    immediate_predecessors.append(self._tool.filesystem.basename(baseline_search_path[index - 1]))
            except ValueError:
                # baseline_search_path.index() throws a ValueError if the item isn't in the list.
                pass
        return immediate_predecessors

    def _port_for_primary_baseline(self, baseline):
        """Returns a Port object for the given baseline directory base name."""
        for port in [self._tool.port_factory.get(port_name) for port_name in self._tool.port_factory.all_port_names()]:
            if self._tool.filesystem.basename(port.baseline_version_dir()) == baseline:
                return port
        raise Exception('Failed to find port for primary baseline %s.' % baseline)

    def _copy_existing_baseline(self, builder_name, test_name, suffix):
        """Copies the baseline for the given builder to all "predecessor" directories."""
        baseline_directory = self._baseline_directory(builder_name)
        ports = [self._port_for_primary_baseline(baseline)
                 for baseline in self._immediate_predecessors_in_fallback(baseline_directory)]

        old_baselines = []
        new_baselines = []

        # Need to gather all the baseline paths before modifying the filesystem since
        # the modifications can affect the results of port.expected_filename.
        for port in ports:
            old_baseline = port.expected_filename(test_name, '.' + suffix)
            if not self._tool.filesystem.exists(old_baseline):
                _log.debug('No existing baseline for %s.', test_name)
                continue

            new_baseline = self._tool.filesystem.join(
                port.baseline_version_dir(),
                self._file_name_for_expected_result(test_name, suffix))
            if self._tool.filesystem.exists(new_baseline):
                _log.debug('Existing baseline at %s, not copying over it.', new_baseline)
                continue

            generic_expectations = TestExpectations(port, tests=[test_name], include_overrides=False)
            full_expectations = TestExpectations(port, tests=[test_name], include_overrides=True)
            # TODO(qyearsley): Change Port.skips_test so that this can be simplified.
            if SKIP in full_expectations.get_expectations(test_name):
                _log.debug('%s is skipped (perhaps temporarily) on %s.', test_name, port.name())
                continue
            if port.skips_test(test_name, generic_expectations, full_expectations):
                _log.debug('%s is skipped on %s.', test_name, port.name())
                continue

            old_baselines.append(old_baseline)
            new_baselines.append(new_baseline)

        for i in range(len(old_baselines)):
            old_baseline = old_baselines[i]
            new_baseline = new_baselines[i]

            _log.debug('Copying baseline from %s to %s.', old_baseline, new_baseline)
            self._tool.filesystem.maybe_make_directory(self._tool.filesystem.dirname(new_baseline))
            self._tool.filesystem.copyfile(old_baseline, new_baseline)

    def execute(self, options, args, tool):
        self._tool = tool
        for suffix in options.suffixes.split(','):
            self._copy_existing_baseline(options.builder, options.test, suffix)


class RebaselineTest(AbstractRebaseliningCommand):
    name = 'rebaseline-test-internal'
    help_text = 'Rebaseline a single test from a buildbot. Only intended for use by other webkit-patch commands.'

    def __init__(self):
        super(RebaselineTest, self).__init__(options=[
            self.results_directory_option,
            self.suffixes_option,
            self.builder_option,
            self.test_option,
            self.build_number_option,
        ])

    def _save_baseline(self, data, target_baseline):
        if not data:
            _log.debug('No baseline data to save.')
            return

        filesystem = self._tool.filesystem
        filesystem.maybe_make_directory(filesystem.dirname(target_baseline))
        filesystem.write_binary_file(target_baseline, data)

    def _rebaseline_test(self, builder_name, test_name, suffix, results_url):
        baseline_directory = self._baseline_directory(builder_name)

        source_baseline = '%s/%s' % (results_url, self._file_name_for_actual_result(test_name, suffix))
        target_baseline = self._tool.filesystem.join(baseline_directory, self._file_name_for_expected_result(test_name, suffix))

        _log.debug('Retrieving source %s for target %s.', source_baseline, target_baseline)
        self._save_baseline(self._tool.web.get_binary(source_baseline, return_none_on_404=True),
                            target_baseline)

    def _rebaseline_test_and_update_expectations(self, options):
        self._baseline_suffix_list = options.suffixes.split(',')

        port = self._tool.port_factory.get_from_builder_name(options.builder)
        if port.reference_files(options.test):
            if 'png' in self._baseline_suffix_list:
                _log.warning('Cannot rebaseline image result for reftest: %s', options.test)
                return
            assert self._baseline_suffix_list == ['txt']

        if options.results_directory:
            results_url = 'file://' + options.results_directory
        else:
            results_url = self._tool.buildbot.results_url(options.builder, build_number=options.build_number)

        for suffix in self._baseline_suffix_list:
            self._rebaseline_test(options.builder, options.test, suffix, results_url)
        self.expectation_line_changes.remove_line(test=options.test, builder=options.builder)

    def execute(self, options, args, tool):
        self._tool = tool
        self._rebaseline_test_and_update_expectations(options)
        self._print_expectation_line_changes()


class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand):
    """Base class for rebaseline commands that do some tasks in parallel."""
    # Not overriding execute() - pylint: disable=abstract-method

    def __init__(self, options=None):
        super(AbstractParallelRebaselineCommand, self).__init__(options=options)

    def _release_builders(self):
        """Returns a list of builder names for continuous release builders.

        The release builders cycle much faster than the debug ones and cover all the platforms.
        """
        release_builders = []
        for builder_name in self._tool.builders.all_continuous_builder_names():
            port = self._tool.port_factory.get_from_builder_name(builder_name)
            if port.test_configuration().build_type == 'release':
                release_builders.append(builder_name)
        return release_builders

    def _run_webkit_patch(self, args, verbose):
        try:
            verbose_args = ['--verbose'] if verbose else []
            stderr = self._tool.executive.run_command([self._tool.path()] + verbose_args +
                                                      args, cwd=self._tool.git().checkout_root, return_stderr=True)
            for line in stderr.splitlines():
                _log.warning(line)
        except ScriptError:
            traceback.print_exc(file=sys.stderr)

    def _builders_to_fetch_from(self, builders_to_check):
        """Returns the subset of builders that will cover all of the baseline
        search paths used in the input list.

        In particular, if the input list contains both Release and Debug
        versions of a configuration, we *only* return the Release version
        (since we don't save debug versions of baselines).

        Args:
            builders_to_check: List of builder names.
        """
        release_builders = set()
        debug_builders = set()
        builders_to_fallback_paths = {}
        for builder in builders_to_check:
            port = self._tool.port_factory.get_from_builder_name(builder)
            if port.test_configuration().build_type == 'release':
                release_builders.add(builder)
            else:
                debug_builders.add(builder)
        for builder in list(release_builders) + list(debug_builders):
            port = self._tool.port_factory.get_from_builder_name(builder)
            fallback_path = port.baseline_search_path()
            if fallback_path not in builders_to_fallback_paths.values():
                builders_to_fallback_paths[builder] = fallback_path
        return builders_to_fallback_paths.keys()

    @staticmethod
    def _builder_names(builds):
        # TODO(qyearsley): If test_prefix_list dicts are converted to instances
        # of some class, then this could be replaced with  a method on that class.
        return [b.builder_name for b in builds]

    def _rebaseline_commands(self, test_prefix_list, options):
        path_to_webkit_patch = self._tool.path()
        cwd = self._tool.git().checkout_root
        copy_baseline_commands = []
        rebaseline_commands = []
        lines_to_remove = {}
        port = self._tool.port_factory.get()

        for test_prefix in test_prefix_list:
            for test in port.tests([test_prefix]):
                builders_to_fetch_from = self._builders_to_fetch_from(self._builder_names(test_prefix_list[test_prefix]))
                for build in sorted(test_prefix_list[test_prefix]):
                    builder, build_number = build.builder_name, build.build_number
                    if builder not in builders_to_fetch_from:
                        break
                    else:
                        actual_failures_suffixes = self._suffixes_for_actual_failures(
                            test, build, test_prefix_list[test_prefix][build])
                    if not actual_failures_suffixes:
                        # If we're not going to rebaseline the test because it's passing on this
                        # builder, we still want to remove the line from TestExpectations.
                        if test not in lines_to_remove:
                            lines_to_remove[test] = []
                        lines_to_remove[test].append(builder)
                        continue

                    suffixes = ','.join(actual_failures_suffixes)
                    args = ['--suffixes', suffixes, '--builder', builder, '--test', test]

                    if options.verbose:
                        args.append('--verbose')

                    copy_baseline_commands.append(
                        tuple([[self._tool.executable, path_to_webkit_patch, 'copy-existing-baselines-internal'] + args, cwd]))

                    if build_number:
                        args.extend(['--build-number', str(build_number)])
                    if options.results_directory:
                        args.extend(['--results-directory', options.results_directory])

                    rebaseline_commands.append(
                        tuple([[self._tool.executable, path_to_webkit_patch, 'rebaseline-test-internal'] + args, cwd]))
        return copy_baseline_commands, rebaseline_commands, lines_to_remove

    @staticmethod
    def _extract_expectation_line_changes(command_results):
        """Parses the JSON lines from sub-command output and returns the result as a ChangeSet."""
        change_set = ChangeSet()
        for _, stdout, _ in command_results:
            updated = False
            for line in filter(None, stdout.splitlines()):
                try:
                    parsed_line = json.loads(line)
                    change_set.update(ChangeSet.from_dict(parsed_line))
                    updated = True
                except ValueError:
                    _log.debug('"%s" is not a JSON object, ignoring', line)
            if not updated:
                # TODO(qyearsley): This probably should be an error. See http://crbug.com/649412.
                _log.debug('Could not add file based off output "%s"', stdout)
        return change_set

    def _optimize_baselines(self, test_prefix_list, verbose=False):
        optimize_commands = []
        for test in test_prefix_list:
            all_suffixes = set()
            builders_to_fetch_from = self._builders_to_fetch_from(self._builder_names(test_prefix_list[test]))
            for build in sorted(test_prefix_list[test]):
                if build.builder_name not in builders_to_fetch_from:
                    break
                all_suffixes.update(self._suffixes_for_actual_failures(test, build, test_prefix_list[test][build]))

            # No need to optimize baselines for a test with no failures.
            if not all_suffixes:
                continue

            # FIXME: We should propagate the platform options as well.
            cmd_line = ['--suffixes', ','.join(all_suffixes), test]
            if verbose:
                cmd_line.append('--verbose')

            path_to_webkit_patch = self._tool.path()
            cwd = self._tool.git().checkout_root
            optimize_commands.append(tuple([[self._tool.executable, path_to_webkit_patch, 'optimize-baselines'] + cmd_line, cwd]))
        return optimize_commands

    def _update_expectations_files(self, lines_to_remove):
        # FIXME: This routine is way too expensive. We're creating O(n ports) TestExpectations objects.
        # This is slow and uses a lot of memory.
        tests = lines_to_remove.keys()
        to_remove = []

        # This is so we remove lines for builders that skip this test, e.g. Android skips most
        # tests and we don't want to leave stray [ Android ] lines in TestExpectations..
        # This is only necessary for "webkit-patch rebaseline" and for rebaselining expected
        # failures from garden-o-matic. rebaseline-expectations and auto-rebaseline will always
        # pass the exact set of ports to rebaseline.
        for port_name in self._tool.port_factory.all_port_names():
            port = self._tool.port_factory.get(port_name)
            generic_expectations = TestExpectations(port, tests=tests, include_overrides=False)
            full_expectations = TestExpectations(port, tests=tests, include_overrides=True)
            for test in tests:
                if port.skips_test(test, generic_expectations, full_expectations):
                    for test_configuration in port.all_test_configurations():
                        if test_configuration.version == port.test_configuration().version:
                            to_remove.append((test, test_configuration))

        for test in lines_to_remove:
            for builder in lines_to_remove[test]:
                port = self._tool.port_factory.get_from_builder_name(builder)
                for test_configuration in port.all_test_configurations():
                    if test_configuration.version == port.test_configuration().version:
                        to_remove.append((test, test_configuration))

        port = self._tool.port_factory.get()
        expectations = TestExpectations(port, include_overrides=False)
        expectations_string = expectations.remove_configurations(to_remove)
        path = port.path_to_generic_test_expectations_file()
        self._tool.filesystem.write_text_file(path, expectations_string)

    def _run_in_parallel(self, commands):
        if not commands:
            return {}

        command_results = self._tool.executive.run_in_parallel(commands)
        for _, _, stderr in command_results:
            if stderr:
                _log.error(stderr)

        change_set = self._extract_expectation_line_changes(command_results)

        return change_set.lines_to_remove

    def rebaseline(self, options, test_prefix_list):
        """Downloads new baselines in parallel, then updates expectations files
        and optimizes baselines.

        Args:
            options: An object with the options passed to the current command.
            test_prefix_list: A map of test names to Build objects to file suffixes
                for new baselines. For example:
                {
                    "some/test.html": {Build("builder-1", 412): ["txt"], Build("builder-2", 100): ["txt"]},
                    "some/other.html": {Build("builder-1", 412): ["txt"]}
                }
                This would mean that new text baselines should be downloaded for
                "some/test.html" on both builder-1 (build 412) and builder-2
                (build 100), and new text baselines should be downloaded for
                "some/other.html" but only from builder-1.
                TODO(qyearsley): Replace test_prefix_list everywhere with some
                sort of class that contains the same data.
        """
        if self._tool.git().has_working_directory_changes(pathspec=self._layout_tests_dir()):
            _log.error('There are uncommitted changes in the layout tests directory; aborting.')
            return

        for test, builds_to_check in sorted(test_prefix_list.items()):
            _log.info('Rebaselining %s', test)
            for build, suffixes in sorted(builds_to_check.items()):
                _log.debug('  %s: %s', build, ','.join(suffixes))

        copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = self._rebaseline_commands(
            test_prefix_list, options)
        lines_to_remove = {}

        self._run_in_parallel(copy_baseline_commands)
        lines_to_remove = self._run_in_parallel(rebaseline_commands)

        for test in extra_lines_to_remove:
            if test in lines_to_remove:
                lines_to_remove[test] = lines_to_remove[test] + extra_lines_to_remove[test]
            else:
                lines_to_remove[test] = extra_lines_to_remove[test]

        if lines_to_remove:
            self._update_expectations_files(lines_to_remove)

        if options.optimize:
            # TODO(wkorman): Consider changing temporary branch to base off of HEAD rather than
            # origin/master to ensure we run baseline optimization processes with the same code as
            # auto-rebaseline itself.
            self._run_in_parallel(self._optimize_baselines(test_prefix_list, options.verbose))

        self._remove_all_pass_testharness_baselines(test_prefix_list)

        self._tool.git().add_list(self.unstaged_baselines())

    def unstaged_baselines(self):
        """Returns absolute paths for unstaged (including untracked) baselines."""
        baseline_re = re.compile(r'.*[\\/]LayoutTests[\\/].*-expected\.(txt|png|wav)$')
        unstaged_changes = self._tool.git().unstaged_changes()
        return sorted(self._tool.git().absolute_path(path) for path in unstaged_changes if re.match(baseline_re, path))

    def _remove_all_pass_testharness_baselines(self, test_prefix_list):
        """Removes all of the all-PASS baselines for the given builders and tests.

        In general, for testharness.js tests, the absence of a baseline
        indicates that the test is expected to pass. When rebaselining,
        new all-PASS baselines may be downloaded, but they should not be kept.
        """
        filesystem = self._tool.filesystem
        baseline_paths = self._all_baseline_paths(test_prefix_list)
        for path in baseline_paths:
            if not (filesystem.exists(path) and
                    filesystem.splitext(path)[1] == '.txt'):
                continue
            contents = filesystem.read_text_file(path)
            if is_all_pass_testharness_result(contents):
                _log.info('Removing all-PASS testharness baseline: %s', path)
                filesystem.remove(path)

    def _all_baseline_paths(self, test_prefix_list):
        """Return file paths for all baselines for the given tests and builders.

        Args:
            test_prefix_list: A dict mapping test prefixes, which could be
                directories or full test paths, to builds to baseline suffixes.
                TODO(qyearsley): If a class is added to replace test_prefix_list,
                then this can be made a method on that class.

        Returns:
            A list of absolute paths to possible baseline files,
            which may or may not exist on the local filesystem.
        """
        filesystem = self._tool.filesystem
        baseline_paths = []
        port = self._tool.port_factory.get()

        for test_prefix in test_prefix_list:
            tests = port.tests([test_prefix])
            all_suffixes = set()

            for build, suffixes in test_prefix_list[test_prefix].iteritems():
                all_suffixes.update(suffixes)
                port_baseline_dir = self._baseline_directory(build.builder_name)
                baseline_paths.extend([
                    filesystem.join(port_baseline_dir, self._file_name_for_expected_result(test, suffix))
                    for test in tests for suffix in suffixes
                ])

            baseline_paths.extend([
                filesystem.join(self._layout_tests_dir(), self._file_name_for_expected_result(test, suffix))
                for test in tests for suffix in all_suffixes
            ])

        return sorted(baseline_paths)

    def _layout_tests_dir(self):
        return self._tool.port_factory.get().layout_tests_dir()

    def _suffixes_for_actual_failures(self, test, build, existing_suffixes):
        """Gets the baseline suffixes for actual mismatch failures in some results.

        Args:
            test: A full test path string.
            build: A Build object.
            existing_suffixes: A collection of all suffixes to consider.

        Returns:
            A set of file suffix strings.
        """
        results = self._tool.buildbot.fetch_results(build)
        if not results:
            _log.debug('No results found for build %s', build)
            return set()
        test_result = results.result_for_test(test)
        if not test_result:
            _log.debug('No test result for test %s in build %s', test, build)
            return set()
        return set(existing_suffixes) & TestExpectations.suffixes_for_test_result(test_result)


class RebaselineJson(AbstractParallelRebaselineCommand):
    name = 'rebaseline-json'
    help_text = 'Rebaseline based off JSON passed to stdin. Intended to only be called from other scripts.'

    def __init__(self,):
        super(RebaselineJson, self).__init__(options=[
            self.no_optimize_option,
            self.results_directory_option,
        ])

    def execute(self, options, args, tool):
        self._tool = tool
        self.rebaseline(options, json.loads(sys.stdin.read()))


class RebaselineExpectations(AbstractParallelRebaselineCommand):
    name = 'rebaseline-expectations'
    help_text = 'Rebaselines the tests indicated in TestExpectations.'
    show_in_main_help = True

    def __init__(self):
        super(RebaselineExpectations, self).__init__(options=[
            self.no_optimize_option,
        ] + self.platform_options)
        self._test_prefix_list = None

    @staticmethod
    def _tests_to_rebaseline(port):
        tests_to_rebaseline = {}
        for path, value in port.expectations_dict().items():
            expectations = TestExpectations(port, include_overrides=False, expectations_dict={path: value})
            for test in expectations.get_rebaselining_failures():
                suffixes = TestExpectations.suffixes_for_expectations(expectations.get_expectations(test))
                tests_to_rebaseline[test] = suffixes or BASELINE_SUFFIX_LIST
        return tests_to_rebaseline

    def _add_tests_to_rebaseline(self, port_name):
        builder_name = self._tool.builders.builder_name_for_port_name(port_name)
        if not builder_name:
            return
        tests = self._tests_to_rebaseline(self._tool.port_factory.get(port_name)).items()

        if tests:
            _log.info('Retrieving results for %s from %s.', port_name, builder_name)

        for test_name, suffixes in tests:
            _log.info('    %s (%s)', test_name, ','.join(suffixes))
            if test_name not in self._test_prefix_list:
                self._test_prefix_list[test_name] = {}
            self._test_prefix_list[test_name][Build(builder_name)] = suffixes

    def execute(self, options, args, tool):
        self._tool = tool
        options.results_directory = None
        self._test_prefix_list = {}
        port_names = tool.port_factory.all_port_names(options.platform)
        for port_name in port_names:
            self._add_tests_to_rebaseline(port_name)
        if not self._test_prefix_list:
            _log.warning('Did not find any tests marked Rebaseline.')
            return

        self.rebaseline(options, self._test_prefix_list)


class Rebaseline(AbstractParallelRebaselineCommand):
    name = 'rebaseline'
    help_text = 'Rebaseline tests with results from the build bots.'
    show_in_main_help = True
    argument_names = '[TEST_NAMES]'

    def __init__(self):
        super(Rebaseline, self).__init__(options=[
            self.no_optimize_option,
            # FIXME: should we support the platform options in addition to (or instead of) --builders?
            self.suffixes_option,
            self.results_directory_option,
            optparse.make_option('--builders', default=None, action='append',
                                 help=('Comma-separated-list of builders to pull new baselines from '
                                       '(can also be provided multiple times).')),
        ])

    def _builders_to_pull_from(self):
        return self._tool.user.prompt_with_list(
            'Which builder to pull results from:', self._release_builders(), can_choose_multiple=True)

    def execute(self, options, args, tool):
        self._tool = tool
        if not args:
            _log.error('Must list tests to rebaseline.')
            return

        if options.builders:
            builders_to_check = []
            for builder_names in options.builders:
                builders_to_check += builder_names.split(',')
        else:
            builders_to_check = self._builders_to_pull_from()

        test_prefix_list = {}
        suffixes_to_update = options.suffixes.split(',')

        for builder in builders_to_check:
            for test in args:
                if test not in test_prefix_list:
                    test_prefix_list[test] = {}
                build = Build(builder)
                test_prefix_list[test][build] = suffixes_to_update

        if options.verbose:
            _log.debug('rebaseline-json: ' + str(test_prefix_list))

        self.rebaseline(options, test_prefix_list)
