#!/usr/bin/python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import argparse
from distutils.version import StrictVersion
import logging as log
import os
import re
import shlex
import subprocess
import sys

# Display INFO log messages and up.
log.basicConfig(level=log.INFO, format="%(levelname)s: %(message)s")


def get_tool_requirements_path():
    '''Return the path to tool_requirements.py, at the top of the repo'''
    # top_src_dir is the top of the repository
    top_src_dir = os.path.normpath(os.path.join(os.path.dirname(__file__),
                                                '..'))

    return os.path.join(top_src_dir, 'tool_requirements.py')


class ReqErr(Exception):
    def __init__(self, path, msg):
        self.path = path
        self.msg = msg

    def __str__(self):
        return ('Error parsing tool requirements from {!r}: {}'
                .format(self.path, self.msg))


class ToolReq:
    # A subclass can set this to configure the command that's run to get the
    # version of a tool. If tool_cmd is None, get_version will call "self.tool
    # --version".
    tool_cmd = None

    # Used by get_version. If not None, this is a dictionary that's added to
    # the environment when running the command.
    tool_env = None

    # A subclass can set this to configure _parse_version_output. If set, it
    # should be a Regex object with a single capturing group that captures the
    # version.
    version_regex = None

    def __init__(self, tool, min_version):
        self.tool = tool
        self.min_version = min_version
        self.optional = False

    def _get_tool_cmd(self):
        '''Return the command to run to get the installed version'''
        return self.tool_cmd or [self.tool, '--version']

    def _get_version(self):
        '''Run the tool to get the installed version.

        Raises a RuntimeError on failure. The default version uses the class
        variable tool_cmd to figure out what to run.

        '''

    def _parse_version_output(self, stdout):
        '''Parse the nonempty stdout to get a version number

        Raises a ValueError on failure. The default implementation returns the
        last word of the first line if version_regex is None or the first match
        for version_regex if it is not None.

        '''
        if self.version_regex is None:
            line0 = stdout.split('\n', 1)[0]
            words = line0.rsplit(None, 1)
            if not words:
                raise ValueError('Empty first line.')

            return words[-1]

        for line in stdout.split('\n'):
            match = self.version_regex.match(line.rstrip())
            if match is not None:
                return match.group(1)
        raise ValueError('No line matched version regex.')

    def get_version(self):
        '''Run the tool to get a version.

        Returns a version string on success. Raises a RuntimeError on failure.
        The default version uses the class variable tool_cmd to figure out what
        to run.

        '''
        cmd = self._get_tool_cmd()
        cmd_txt = ' '.join(shlex.quote(w) for w in cmd)

        env = None
        if self.tool_env is not None:
            env = os.environ.copy()
            env.update(self.tool_env)

        try:
            proc = subprocess.run(cmd,
                                  check=True,
                                  stdout=subprocess.PIPE,
                                  universal_newlines=True,
                                  env=env)
        except (subprocess.CalledProcessError, FileNotFoundError) as err:
            env_msg = ('' if not self.tool_env else
                       ' (with environment overrides: {})'
                       .format(', '.join('{}={}'.format(k, v)
                                         for k, v in self.tool_env.items())))
            raise RuntimeError('Failed to run {!r}{} to check version: {}'
                               .format(cmd_txt, env_msg, err))

        if not proc.stdout:
            raise RuntimeError('No output from running {!r} to check version.'
                               .format(cmd_txt))

        try:
            return self._parse_version_output(proc.stdout)
        except ValueError as err:
            raise RuntimeError('Bad output from running {!r} '
                               'to check version: {}'
                               .format(cmd_txt, err))

    def to_semver(self, version, from_req):
        '''Convert a tool version to semantic versioning format

        If from_req is true, this version comes from the requirements file
        (rather than being reported from an installed application). That might
        mean stricter checking. If version is not a known format, raises a
        ValueError.

        '''
        return version

    def check(self):
        '''Get the installed version and check it matches the requirements

        Returns (is_good, msg). is_good is true if we matched the requirements
        and false otherwise. msg describes what happened (an error message on
        failure, or extra information on success).

        '''
        try:
            min_semver = self.to_semver(self.min_version, True)
        except ValueError as err:
            return (False,
                    'Failed to convert requirement to semantic version: {}'
                    .format(err))
        try:
            min_sv = StrictVersion(min_semver)
        except ValueError as err:
            return (False,
                    'Bad semver inferred from required version ({}): {}'
                    .format(min_semver, err))

        try:
            actual_version = self.get_version()
        except RuntimeError as err:
            return (False, str(err))

        try:
            actual_semver = self.to_semver(actual_version, False)
        except ValueError as err:
            return (False,
                    'Failed to convert installed to semantic version: {}'
                    .format(err))
        try:
            actual_sv = StrictVersion(actual_semver)
        except ValueError as err:
            return (False,
                    'Bad semver inferred from installed version ({}): {}'
                    .format(actual_semver, err))

        if actual_sv < min_sv:
            return (False,
                    'Installed version is too old: '
                    'found version {}, but need at least {}'
                    .format(actual_version, self.min_version))

        return (True,
                'Sufficiently recent version (found {}; needed {})'
                .format(actual_version, self.min_version))


class VerilatorToolReq(ToolReq):
    def get_version(self):
        try:
            # Note: "verilator" needs to be called through a shell and with all
            # arguments in a string, as it doesn't have a shebang, but instead
            # relies on perl magic to parse command line arguments.
            version_str = subprocess.run('verilator --version', shell=True,
                                         check=True, stdout=subprocess.PIPE,
                                         stderr=subprocess.STDOUT,
                                         universal_newlines=True)
        except subprocess.CalledProcessError as err:
            raise RuntimeError('Unable to call Verilator to check version: {}'
                               .format(err)) from None

        return version_str.stdout.split(' ')[1].strip()


class VeribleToolReq(ToolReq):
    tool_cmd = ['verible-verilog-lint', '--version']

    def to_semver(self, version, from_req):
        # Drop the hash suffix and convert into version string that
        # is compatible with StrictVersion in check_version below.
        # Example: v0.0-808-g1e17daa -> 0.0.808
        m = re.fullmatch(r'v([0-9]+)\.([0-9]+)-([0-9]+)-g[0-9a-f]+$', version)
        if m is None:
            raise ValueError("{} has invalid version string format."
                             .format(version))

        return '.'.join(m.group(1, 2, 3))


class VcsToolReq(ToolReq):
    tool_cmd = ['vcs', '-full64', '-ID']
    tool_env = {'VCS_ARCH_OVERRIDE': 'linux'}
    version_regex = re.compile(r'Compiler version = VCS [A-Z]-(.*)')

    def to_semver(self, version, from_req):
        # VCS has a rather strange numbering scheme, where the most general
        # versions look something like this:
        #
        #    Q-2020.03-SP1-2
        #
        # Our version_regex strips out the "Q" part (a "platform prefix")
        # already. A version always has the "2020.03" (year and month) part,
        # and may also have an -SP<n> and/or -<patch> suffix.
        #
        # Since StrictVersion expects a 3 digit versioning scheme, we multiply
        # any SP number by 100, which should work as long as the patch version
        # isn't greater than 99.
        #
        # Some VCS builds also report other cruft (like _Full64) after this
        # version number. If from_req is False, allow (and ignore) that too.
        regex = r'([0-9]+).([0-9]+)(?:-SP([0-9]+))?(?:-([0-9]+))?'
        if from_req:
            regex += '$'

        match = re.match(regex, version)
        if match is None:
            raise ValueError("{!r} is not a recognised VCS version string."
                             .format(version))
        major = match.group(1)
        minor = match.group(2)
        sp = int(match.group(3) or 0)
        patch = int(match.group(4) or 0)
        comb = str(sp * 100 + patch)
        return '{}.{}{}'.format(major, minor, comb)


class PyModuleToolReq(ToolReq):
    '''A tool in a Python module (its version can be found by running pip)'''
    version_regex = re.compile(r'Version: (.*)')

    def _get_tool_cmd(self):
        return ['pip3', 'show', self.tool]


def dict_to_tool_req(path, tool, raw):
    '''Parse a dict (as read from Python) as a ToolReq

    Required keys: version. Optional keys: as_needed.

    '''
    where = 'Dict for {} in __TOOL_REQUIREMENTS__'.format(tool)
    # We operate in place on the dictionary. Take a copy to avoid an
    # obnoxious API.
    raw = raw.copy()

    if 'min_version' not in raw:
        raise ReqErr(path,
                     '{} is missing required key: "min_version".'
                     .format(where))
    min_version = raw['min_version']
    if not isinstance(min_version, str):
        raise ReqErr(path,
                     '{} has min_version that is not a string.'
                     .format(where))
    del raw['min_version']

    as_needed = False
    if 'as_needed' in raw:
        as_needed = raw['as_needed']
        if not isinstance(as_needed, bool):
            raise ReqErr(path,
                         '{} has as_needed that is not a bool.'
                         .format(where))
        del raw['as_needed']

    if raw:
        raise ReqErr(path,
                     '{} has unexpected keys: {}.'
                     .format(where, ', '.join(raw.keys())))

    classes = {
        'edalize': PyModuleToolReq,
        'vcs': VcsToolReq,
        'verible': VeribleToolReq,
        'verilator': VerilatorToolReq
    }
    cls = classes.get(tool, ToolReq)

    ret = cls(tool, min_version)
    ret.as_needed = as_needed
    return ret


def read_tool_requirements(path=None):
    '''Read tool requirements from a Python file'''
    if path is None:
        path = get_tool_requirements_path()

    with open(path, 'r') as pyfile:
        globs = {}
        exec(pyfile.read(), globs)

        # We expect the exec call to have populated globs with a
        # __TOOL_REQUIREMENTS__ dictionary.
        raw = globs.get('__TOOL_REQUIREMENTS__')
        if raw is None:
            raise ReqErr(path,
                         'The Python file at did not define '
                         '__TOOL_REQUIREMENTS__.')

        # raw should be a dictionary (keyed by tool name)
        if not isinstance(raw, dict):
            raise ReqErr(path, '__TOOL_REQUIREMENTS__ is not a dict.')

        reqs = {}
        for tool, raw_val in raw.items():
            if not isinstance(tool, str):
                raise ReqErr(path,
                             'Invalid key in __TOOL_REQUIREMENTS__: {!r}'
                             .format(tool))

            if isinstance(raw_val, str):
                # Shorthand notation: value is just a string, which we
                # interpret as a minimum version
                raw_val = {'min_version': raw_val}

            if not isinstance(raw_val, dict):
                raise ReqErr(path,
                             'Value for {} in __TOOL_REQUIREMENTS__ '
                             'is not a string or dict.'.format(tool))

            reqs[tool] = dict_to_tool_req(path, tool, raw_val)

        return reqs


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('tool', nargs='*')
    args = parser.parse_args()

    # Get tool requirements
    try:
        tool_requirements = read_tool_requirements()
    except ReqErr as err:
        log.error(str(err))
        return 1

    pending_tools = set(args.tool)
    missing_tools = []
    for tool, req in tool_requirements.items():
        if req.as_needed and tool not in pending_tools:
            continue
        pending_tools.discard(tool)

        good, msg = req.check()
        if not good:
            log.error('Failed tool requirement for {}: {}'
                      .format(tool, msg))
            missing_tools.append(tool)
        else:
            log.info('Tool {} present: {}'
                     .format(tool, msg))

    all_good = True
    if missing_tools:
        log.error("Tool requirements not fulfilled. "
                  "Please update tools ({}) and retry."
                  .format(', '.join(missing_tools)))
        all_good = False

    if pending_tools:
        log.error("Some tools specified on command line don't appear in "
                  "tool requirements file: {}"
                  .format(', '.join(sorted(pending_tools))))
        all_good = False

    return 0 if all_good else 1


if __name__ == "__main__":
    sys.exit(main())
