#!/usr/bin/env python3
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Custom swarming base trigger class.

This base class consolidates custom swarming triggering logic, to allow one bot
to conceptually span multiple Swarming configurations, while lumping all trigger
calls under one logical step.  It also gives the subclasses the ability to
define their own logic for pruning the configurations they want to trigger
jobs on and what configurations to use.

See perf_device_triggerer.py for an example of how to use this base class.

"""

import copy
import json
import os
import subprocess
import sys
import tempfile
import time
import logging
import six

SRC_DIR = os.path.dirname(
    os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# .exe on Windows.
EXECUTABLE_SUFFIX = '.exe' if sys.platform == 'win32' else ''

SWARMING_GO = os.path.join(SRC_DIR, 'tools', 'luci-go',
                           'swarming' + EXECUTABLE_SUFFIX)

_A_WEEK_IN_SECONDS = 60 * 60 * 24 * 7


def convert_to_go_swarming_args(args):
    go_args = []
    i = 0
    while i < len(args):
        current_arg = args[i]
        if current_arg == '--swarming':
            current_arg = '--server'
        go_args.append(current_arg)
        i += 1
        if current_arg == '--dimension':
            go_args.append('{}={}'.format(args[i], args[i + 1]))
            i += 2
    return go_args


def strip_unicode(obj):
    """Recursively re-encodes strings as utf-8 inside |obj|. Returns the result.
  """
    if isinstance(obj, six.text_type):
        return obj.encode('utf-8', 'replace')
    if isinstance(obj, list):
        return list(map(strip_unicode, obj))

    if isinstance(obj, dict):
        new_obj = type(obj)(
            (strip_unicode(k), strip_unicode(v)) for k, v in obj.items())
        return new_obj
    return obj


class BaseTestTriggerer(object):  # pylint: disable=useless-object-inheritance

    def __init__(self):
        self._bot_configs = None
        self._bot_statuses = []
        self._total_bots = 0

    def modify_args(self,
                    all_args,
                    bot_index,
                    shard_index,
                    total_shards,
                    temp_file,
                    shard_map=None):
        """Modifies the given argument list.

    Specifically, it does the following:
      * Adds a --dump_json argument, to read in the results of the
        individual trigger command.
      * Adds the dimensions associated with the bot config at the given index.
      * If the number of shards is greater than one, adds --env
        arguments to set the GTEST_SHARD_INDEX and GTEST_TOTAL_SHARDS
        environment variables to _shard_index_ and _total_shards_,
        respectively.

    The arguments are structured like this:
    <args to swarming trigger> -- <args to bot running isolate>
    This means we have to add arguments to specific locations in the argument
    list, to either affect the trigger command, or what the bot runs.

    """
        bot_args = ['--dump-json', temp_file]
        if total_shards > 1:
            bot_args.append('--env')
            bot_args.append('GTEST_SHARD_INDEX=%s' % shard_index)
            bot_args.append('--env')
            bot_args.append('GTEST_TOTAL_SHARDS=%s' % total_shards)
        if self._bot_configs:
            for key, val in sorted(self._bot_configs[bot_index].items()):
                bot_args.append('--dimension')
                bot_args.append(key)
                bot_args.append(val)
        if '--' in all_args:
            dash_ind = all_args.index('--')
            additional_args = all_args[:dash_ind] + bot_args + all_args[
                dash_ind:]
        else:
            additional_args = all_args + bot_args
        additional_args = self.append_additional_args(additional_args,
                                                      shard_index)
        # crbug/1140389: debug print outs
        logging.info('DEBUG: Before adding shardmap args: %s', additional_args)
        if shard_map:
            shard_map_str = json.dumps(shard_map, separators=(',', ':'))
            shard_map_args = ['--use-dynamic-shards']
            shard_map_args.append('--dynamic-shardmap=%s' % shard_map_str)
            additional_args += shard_map_args
        return additional_args

    # Overridden by subclasses.
    # pylint: disable=no-self-use
    def append_additional_args(self, args, shard_index):
        """ Gives subclasses ability to append additional args if necessary
    # pylint: enable=no-self-use

    Base class just returns given args."""
        del shard_index  # unused
        return args

    def parse_bot_configs(self, args):
        try:
            self._bot_configs = strip_unicode(
                json.loads(args.multiple_trigger_configs))
        except json.JSONDecodeError as e:
            raise ValueError(
                'Error while parsing JSON from bot config string %s: %s' %
                (args.multiple_trigger_configs, str(e))) from e
        # Validate the input.
        if not isinstance(self._bot_configs, list):
            raise ValueError('Bot configurations must be a list, were: %s' %
                             args.multiple_trigger_configs)
        if len(self._bot_configs) < 1:
            raise ValueError(
                'Bot configuration list must have at least one entry')
        if not all(isinstance(entry, dict) for entry in self._bot_configs):
            raise ValueError('Bot configurations must all be dictionaries')

    # Overridden for testing.
    # pylint: disable=no-self-use
    def list_bots(self, dimensions, server='chromium-swarm.appspot.com'):
        """List bots having specified bot dimensions.

        Type of returned value is list of
        https://source.chromium.org/search?q=%22class%20BotInfo(messages.Message)%22%20f:luci%2Fappengine%2Fswarming&ssfr=1
        """

        args = [SWARMING_GO, 'bots', '-server', server]

        for key in sorted(dimensions):
            args.extend(['-dimension', '%s=%s' % (key, dimensions[key])])

        logging.info('Running Go `swarming` with args: %s', args)

        with tempfile.NamedTemporaryFile(delete=False) as result_json:
            result_json.close()
            args.extend(['--json', result_json.name])
            subprocess.check_call(args)
            with open(result_json.name) as f:
                return json.load(f)
    # pylint: enable=no-self-use

    # Overridden for testing.
    # pylint: disable=no-self-use
    def list_tasks(self, tags, limit=None, server='chromium-swarm.appspot.com'):
        """List bots having specified task tags.

        Type of returned value is list of
        https://source.chromium.org/search?q=%22class%20TaskResult(messages.Message):%22%20f:luci%2Fappengine%2Fswarming&ssfr=1
        """

        args = [SWARMING_GO, 'tasks', '-server', server]

        for tag in sorted(tags):
            args.extend(['-tag', tag])

        # If a query uses a general dimension value, e.g., os:Mac, it will take
        # forever. We now limited the time range to be within a week.
        start_epoch_time = int(time.time()) - _A_WEEK_IN_SECONDS
        args.extend(['-start', str(start_epoch_time)])

        if limit is not None:
            args.extend(['-limit', str(limit)])

        logging.info('Running Go `swarming` with args: %s', args)

        with tempfile.NamedTemporaryFile(delete=False) as result_json:
            result_json.close()
            args.extend(['-json', result_json.name])
            subprocess.check_call(args)
            with open(result_json.name) as f:
                return json.load(f)
    # pylint: enable=no-self-use

    # Overridden for testing.
    # pylint: disable=no-self-use
    def make_temp_file(self, prefix=None, suffix=None):
        # This trick of closing the file handle is needed on Windows in order to
        # make the file writeable.
        h, temp_file = tempfile.mkstemp(prefix=prefix, suffix=suffix)
        os.close(h)
        return temp_file
    # pylint: enable=no-self-use

    # Overridden for testing.
    # pylint: disable=no-self-use
    def delete_temp_file(self, temp_file):
        os.remove(temp_file)
    # pylint: enable=no-self-use

    # Overridden for testing.
    # pylint: disable=no-self-use
    def read_json_from_temp_file(self, temp_file):
        with open(temp_file) as f:
            return json.load(f)
    # pylint: enable=no-self-use

    # Overridden for testing.
    # pylint: disable=no-self-use
    def read_encoded_json_from_temp_file(self, temp_file):
        return strip_unicode(self.read_json_from_temp_file(temp_file))
    # pylint: enable=no-self-use

    # Overridden for testing.
    # pylint: disable=no-self-use
    def write_json_to_file(self, merged_json, output_file):
        with open(output_file, 'w') as f:
            json.dump(merged_json, f)
    # pylint: enable=no-self-use

    def run_swarming_go(self,
                        args,
                        json_path,
                        shard_index,
                        shards,
                        merged_json=None):

        logging.info('Running Go `swarming` with args: %s', args)

        if merged_json is None:
            merged_json = {}

        if 'tasks' not in merged_json:
            merged_json['tasks'] = {}

        ret = subprocess.call([SWARMING_GO] + convert_to_go_swarming_args(args))
        result_json = self.read_json_from_temp_file(json_path)

        tasks = {}
        for task in result_json['tasks']:
            k = task['request']['task_id']
            tasks[k] = task['request']
            invocation = task.get('task_result', {}).get('resultdb_info',
                                                         {}).get('invocation')
            if invocation:
                tasks[k]['invocation'] = invocation

        for k, v in tasks.items():
            v['shard_index'] = shard_index
            merged_json['tasks'][k + ':%d:%d' % (shard_index, shards)] = v
        self.write_json_to_file(merged_json, json_path)
        return ret

    def prune_test_specific_configs(self, args):
        # Ability for base class to further prune configs to
        # run tests on.
        pass

    def select_config_indices(self, args):
        # Main implementation for base class to determine which bot config to
        # trigger for each shard.
        #
        # Returns a list of tuples (shard_index, bot_config_index).
        # bot_config_index is an index into self._bot_configs
        pass

    def generate_shard_map(self, args, buildername, selected_config):
        """Returns shard map generated on runtime if needed."""
        pass  # pylint: disable=unnecessary-pass

    def trigger_tasks(self, args, remaining):
        """Triggers tasks for each bot.

        Args:
            args: Parsed arguments which we need to use.
            remaining: The remainder of the arguments, which should be passed to
              swarming.py calls.

        Returns:
            Exit code for the script.
        """
        if args.multiple_dimension_script_verbose:
            logging.basicConfig(level=logging.DEBUG)

        # crbug/1140389: debug print outs
        logging.info('DEBUG: init: %s', remaining)

        self.parse_bot_configs(args)
        # Prunes config list to the exact set of configurations to trigger jobs
        # on. This logic is specific to the base class if they want to prune
        # list further.
        self.prune_test_specific_configs(args)

        # In the remaining arguments, find the Swarming dimensions that are
        # specified by the bot configs and remove them, because for each shard,
        # we're going to select one of the bot configs and put all of its
        # Swarming dimensions on the command line.
        filtered_remaining_args = copy.deepcopy(remaining)
        for config in self._bot_configs:
            for k in config.keys():
                filtered_remaining_args = remove_swarming_dimension(
                    filtered_remaining_args, k)
        # crbug/1140389: debug print outs
        logging.info('DEBUG: After filtered: %s', filtered_remaining_args)

        merged_json = {}
        #pylint: disable=assignment-from-no-return
        selected_config = self.select_config_indices(args)
        shard_map = self.generate_shard_map(
            args, _findBuilderName(filtered_remaining_args), selected_config)
        #pylint: enable=assignment-from-no-return
        # Choose selected configs for this run of the test suite.
        for shard_index, bot_index in selected_config:
            # For each shard that we're going to distribute, do the following:
            # 1. Pick which bot configuration to use.
            # 2. Insert that bot configuration's dimensions as command line
            #    arguments, and invoke "swarming.py trigger".
            # Holds the results of the swarming.py trigger call.
            try:
                json_temp = self.make_temp_file(
                    prefix='base_trigger_dimensions', suffix='.json')
                # crbug/1140389: debug print outs
                logging.info('DEBUG: Before modify args: %s',
                             filtered_remaining_args)
                args_to_pass = self.modify_args(filtered_remaining_args,
                                                bot_index, shard_index,
                                                args.shards, json_temp,
                                                shard_map)
                # crbug/1140389: debug print outs
                logging.info('DEBUG: Before calling swarming: %s', args_to_pass)
                ret = self.run_swarming_go(args_to_pass, json_temp, shard_index,
                                           args.shards, merged_json)
                if ret:
                    sys.stderr.write('Failed to trigger a task, aborting\n')
                    return ret
            finally:
                self.delete_temp_file(json_temp)
        self.write_json_to_file(merged_json, args.dump_json)
        return 0

    @staticmethod
    def setup_parser_contract(parser):
        parser.add_argument(
            '--multiple-trigger-configs',
            type=str,
            required=False,
            help='The Swarming configurations to trigger tasks on, '
            'in the form of a JSON array of dictionaries (these are'
            ' Swarming dimension_sets). At least one entry is'
            'required if you dont override parse_bot_configs')
        parser.add_argument('--multiple-dimension-script-verbose',
                            type=bool,
                            default=False,
                            help='Turn on verbose logging')
        parser.add_argument(
            '--dump-json',
            required=True,
            help='(Swarming Trigger Script API) Where to dump the'
            ' resulting json which indicates which tasks were'
            ' triggered for which shards.')
        parser.add_argument(
            '--shards',
            type=int,
            default=1,
            help='How many shards to trigger. Duplicated from the'
            ' `swarming.py trigger` command.')
        parser.add_argument('--shard-index',
                            type=int,
                            default=None,
                            help='Which shard to trigger. Duplicated from the '
                            '`swarming.py trigger` command.')
        return parser


def remove_swarming_dimension(args, dimension):
    for i, argument in enumerate(args):
        if argument == '--dimension' and args[i + 1] == dimension:
            return args[:i] + args[i + 3:]
    return args


def indices_to_trigger(args):
    """Returns the indices of the swarming shards that should be
    triggered."""
    if args.shard_index is None:
        return list(range(args.shards))
    return [args.shard_index]


def _findBuilderName(args):
    args_length = len(args)
    for i in range(args_length):
        if (args[i] == '--tag' and i < args_length - 1
                and args[i + 1].startswith('buildername:')):
            return args[i + 1].split(':', 1)[1]
    return None
