#!/usr/bin/env python3
# Copyright (c) 2020 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Utitilies to flash or erase a device."""

import argparse
import errno
import locale
import os
import pathlib
import stat
import subprocess
import sys
import textwrap
import traceback

# Here are the options that can be use to configure a `Flasher`
# object (as dictionary keys) and/or passed as command line options.

OPTIONS = {
    # Configuration options define properties used in flashing operations.
    # (The outer level of an options definition corresponds to option groups
    # in the command-line help message.)
    'configuration': {
        # Script configuration options.
        'verbose': {
            'help': 'Report more verbosely',
            'default': 0,
            'alias': ['-v'],
            'argparse': {
                'action': 'count',
            },
            # Levels:
            #   0   - error message
            #   1   - action to be taken
            #   2   - results of action, even if successful
            #   3+  - details
        },
    },

    # Action control options specify operations that Flasher.action() or
    # the function interface flash_command() will perform.
    'operations': {
        # Action control options.
        'erase': {
            'help': 'Erase device',
            'default': False,
            'argparse': {
                'action': 'store_true'
            },
        },
        'application': {
            'help': 'Flash an image',
            'default': None,
            'argparse': {
                'metavar': 'FILE',
                'type': pathlib.Path,
            },
        },
        'verify_application': {
            'help': 'Verify the image after flashing',
            'default': False,
            'argparse': {
                'action': 'store_true'
            },
        },
        # 'reset' is a three-way switch; if None, action() will reset the
        # device if and only if an application image is flashed. So, we add
        # an explicit option to set it false.
        'reset': {
            'help': 'Reset device after flashing',
            'default': None,  # None = Reset iff application was flashed.
            'argparse': {
                'action': 'store_true'
            },
        },
        'skip_reset': {
            'help': 'Do not reset device after flashing',
            'default': None,  # None = Reset iff application was flashed.
            'argparse': {
                'dest': 'reset',
                'action': 'store_false'
            },
        }
    },

    # Internal; these properties do not have command line options
    # (because they don't have an `argparse` key).
    'internal': {
        # Script configuration options.
        'platform': {
            'help': 'Short name of the current platform',
            'default': None,
        },
        'module': {
            'help': 'Invoking Python module, for generating scripts',
            'default': None,
        },
    },
}


class Flasher:
    """Manage flashing."""

    def __init__(self, **options):
        # An integer giving the current Flasher status.
        # 0 if OK, and normally an errno value if positive.
        self.err = 0

        # Namespace of option values.
        self.option = argparse.Namespace(**options)

        # Namespace of option metadata. This contains the option specification
        # information one level down from `define_options()`, i.e. without the
        # group; the keys are mostly the same as those of `self.option`.
        # (Exceptions include options with no metadata and only defined when
        # constructing the Flasher, and options where different command line
        # options (`info` keys) affect a single attribute (e.g. `reset` and
        # `skip-reset` have distinct `info` entries but one option).
        self.info = argparse.Namespace()

        # `argv[0]` from the most recent call to parse_argv(); that is,
        # the path used to invoke the script. This is used to find files
        # relative to the script.
        self.argv0 = None

        # Argument parser for `parse_argv()`. Normally defines command-line
        # options for most of the `self.option` keys.
        self.parser = argparse.ArgumentParser(
            description='Flash {} device'.format(self.option.platform or 'a'))

        # Argument parser groups.
        self.group = {}

        # Construct the global options for all Flasher()s.
        self.define_options(OPTIONS)

    def define_options(self, options):
        """Define options, including setting defaults and argument parsing."""
        for group, group_options in options.items():
            if group not in self.group:
                self.group[group] = self.parser.add_argument_group(group)
            for key, info in group_options.items():
                setattr(self.info, key, info)
                if 'argparse' not in info:
                    continue
                argument = info['argparse']
                attribute = argument.get('dest', key)
                # Set default value.
                if attribute not in self.option:
                    setattr(self.option, attribute, info['default'])
                # Add command line argument.
                names = ['--' + key]
                if '_' in key:
                    names.append('--' + key.replace('_', '-'))
                if 'alias' in info:
                    names += info['alias']
                self.group[group].add_argument(
                    *names,
                    help=info['help'],
                    default=getattr(self.option, attribute),
                    **argument)
        return self

    def status(self):
        """Return the current error code."""
        return self.err

    def actions(self):
        """Perform actions on the device according to self.option."""
        raise NotImplementedError()

    def log(self, level, *args):
        """Optionally log a message to stderr."""
        if self.option.verbose >= level:
            print(*args, file=sys.stderr)

    def run_tool(self,
                 tool,
                 arguments,
                 options=None,
                 name=None,
                 pass_message=None,
                 fail_message=None,
                 fail_level=0,
                 capture_output=False):
        """Run an external tool."""
        if name is None:
            name = 'Run ' + tool
        self.log(1, name)

        option_map = vars(self.option)
        if options:
            option_map.update(options)
        arguments = self.format_command(arguments, opt=option_map)
        if not getattr(self.option, tool, None):
            setattr(self.option, tool, self.locate_tool(tool))
        tool_info = getattr(self.info, tool)
        command_template = tool_info.get('command', ['{' + tool + '}', ()])
        command = self.format_command(command_template, arguments, option_map)
        self.log(3, 'Execute:', *command)

        try:
            if capture_output:
                result = None
                result = subprocess.run(
                    command,
                    check=True,
                    encoding=locale.getpreferredencoding(),
                    capture_output=True)
            else:
                result = self
                self.error = subprocess.check_call(command)
        except subprocess.CalledProcessError as exception:
            self.err = exception.returncode
            if capture_output:
                self.log(fail_level, '--- stdout ---')
                self.log(fail_level, exception.stdout)
                self.log(fail_level, '--- stderr ---')
                self.log(fail_level, exception.stderr)
                self.log(fail_level, '---')
        except FileNotFoundError as exception:
            self.err = exception.errno
            if self.err == errno.ENOENT:
                # This likely means that the program was not found.
                # But if it seems OK, rethrow the exception.
                if self.verify_tool(tool):
                    raise exception

        if self.err:
            self.log(fail_level, fail_message or ('FAILED: ' + name))
        else:
            self.log(2, pass_message or (name + ' complete'))
        return result

    def locate_tool(self, tool):
        """Called to find an undefined tool. (Override in platform.)"""
        return tool

    def verify_tool(self, tool):
        """Run a command to verify that an external tool is available.

        Prints a configurable error and returns False if not.
        """
        tool_info = getattr(self.info, tool)
        command_template = tool_info.get('verify')
        if not command_template:
            return True
        command = self.format_command(command_template, opt=vars(self.option))
        try:
            self.err = subprocess.call(command)
        except OSError as ex:
            self.err = ex.errno
        if self.err:
            note = tool_info.get('error', 'Unable to execute {tool}.')
            note = textwrap.dedent(note).format(tool=tool, **vars(self.option))
            # textwrap.fill only handles single paragraphs:
            note = '\n\n'.join((textwrap.fill(p) for p in note.split('\n\n')))
            print(note, file=sys.stderr)
            return False
        return True

    def format_command(self, template, args=None, opt=None):
        """Construct a tool command line.

        This provides a few conveniences over a simple list of fixed strings,
        that in most cases eliminates any need for custom code to build a tool
        command line. In this description, φ(τ) is the result of formatting a
        template τ.

            template  ::= list | () | str | dict

        Typically the caller provides a list, and `format_command()` returns a
        formatted list. The results of formatting sub-elements get interpolated
        into the end result.

            list      ::= [τ₀, …, τₙ]
                        ↦ φ(τ₀) + … + φ(τₙ)

        An empty tuple returns the supplied `args`. Typically this would be
        used for things like subcommands or file names at the end of a command.

            ()          ↦ args or []

        Formatting a string uses the Python string formatter with the `opt`
        map as arguments. Typically used to interpolate an option value into
        the command line, e.g. ['--flag', '{flag}'] or ['--flag={flag}'].

            str       ::= σ
                        ↦ [σ.format_map(opt)]

        A dictionary element provides a convenience feature. For any dictionary
        template, if it contains an optional 'expand' key that tests true, the
        result is recursively passed to format_command(); otherwise it is taken
        as is.

        The simplest case is an option propagated to the tool command line,
        as a single option if the value is exactly boolean True or as an
        option-argument pair if otherwise set.

            optional  ::= {'optional': name}
                        ↦ ['--name'] if opt[name] is True
                          ['--name', opt[name]] if opt[name] tests true
                          [] otherwise

        A dictionary with an 'option' can insert command line arguments based
        on the value of an option. The 'result' is optional defaults to the
        option value itself, and 'else' defaults to nothing.

            option    ::= {'option': name, 'result': ρ, 'else': δ}
                        ↦ ρ if opt[name]
                          δ otherwise

        A dictionary with a 'match' key returns a result comparing the value of
        an option against a 'test' list of tuples. The 'else' is optional and
        defaults to nothing.

            match     ::= {'match': name, 'test': [(σᵢ, ρᵢ), …], 'else': ρ}
                        ↦ ρᵢ if opt[name]==σᵢ
                          ρ otherwise
        """
        if isinstance(template, str) or isinstance(template, pathlib.Path):
            result = [str(template).format_map(opt)]
        elif isinstance(template, list):
            result = []
            for i in template:
                result += self.format_command(i, args, opt)
        elif template == ():
            result = args or []
        elif isinstance(template, dict):
            if 'optional' in template:
                name = template['optional']
                value = opt.get(name)
                if value is True:
                    result = ['--' + name]
                elif value:
                    result = ['--' + name, value]
                else:
                    result = []
            elif 'option' in template:
                name = template['option']
                value = opt.get(name)
                if value:
                    result = template.get('result', value)
                else:
                    result = template.get('else')
            elif 'match' in template:
                value = template['match']
                for compare, result in template['test']:
                    if value == compare:
                        break
                else:
                    result = template.get('else')
            if result and template.get('expand'):
                result = self.format_command(result, args, opt)
            elif result is None:
                result = []
            elif not isinstance(result, list):
                result = [result]
        else:
            raise ValueError('Unknown: {}'.format(template))
        return result

    def parse_argv(self, argv):
        """Handle command line options."""
        self.argv0 = argv[0]
        self.parser.parse_args(argv[1:], namespace=self.option)
        self._postprocess_argv()
        return self

    def _postprocess_argv(self):
        """Called after parse_argv() for platform-specific processing."""

    def flash_command(self, argv):
        """Perform device actions according to the command line."""
        return self.parse_argv(argv).actions().status()

    def _platform_wrapper_args(self, args):
        """Called from make_wrapper() to optionally manipulate arguments."""

    def make_wrapper(self, argv):
        """Generate script to flash a device.

        The generated script is a minimal wrapper around `flash_command()`,
        containing any option values that differ from the class defaults.
        """

        # Note: this modifies the argument parser, so the same Flasher instance
        # should not be used for both parse_argv() and make_wrapper().
        self.parser.description = 'Generate a flashing script.'
        self.parser.add_argument(
            '--output',
            metavar='FILENAME',
            required=True,
            help='flashing script name')
        self.argv0 = argv[0]
        args = self.parser.parse_args(argv[1:])

        # Give platform-specific code a chance to manipulate the arguments
        # for the wrapper script.
        try:
            self._platform_wrapper_args(args)
        except OSError:
            traceback.print_last()
            return 1

        # Find any option values that differ from the class defaults.
        # These will be inserted into the wrapper script.
        defaults = []
        for key, value in vars(args).items():
            if key in self.option and value != getattr(self.option, key):
                if isinstance(value, pathlib.Path):
                    defaults.append('  {}: os.path.join(os.path.dirname(sys.argv[0]), {}),'.format(
                        repr(key), repr(str(value))))
                else:
                    defaults.append('  {}: {},'.format(repr(key), repr(value)))

        script = """
            import sys
            import os.path

            DEFAULTS = {{
            {defaults}
            }}

            import {module}

            if __name__ == '__main__':
                sys.exit({module}.Flasher(**DEFAULTS).flash_command(sys.argv))
        """

        script = ('#!/usr/bin/env python3' + textwrap.dedent(script).format(
            module=self.option.module, defaults='\n'.join(defaults)))

        try:
            with open(args.output, 'w') as script_file:
                script_file.write(script)
            os.chmod(args.output, (stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
                                   | stat.S_IXGRP | stat.S_IRGRP
                                   | stat.S_IXOTH | stat.S_IROTH))
        except OSError:
            traceback.print_last()
            return 1
        return 0
