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

from distutils.version import StrictVersion
import logging as log
import os
import re
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')


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.
        reqs = globs.get('__TOOL_REQUIREMENTS__')
        if reqs is None:
            log.error('The Python file at {} did not define '
                      '__TOOL_REQUIREMENTS__.'
                      .format(path))
            return None

        # reqs should be a dictionary (mapping tool name to minimum version)
        if not isinstance(reqs, dict):
            log.error('The Python file at {} defined '
                      '__TOOL_REQUIREMENTS__, but it is not a dict.'
                      .format(path))
            return None

        return reqs


def get_verilator_version():
    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)
        return version_str.stdout.split(' ')[1].strip()

    except subprocess.CalledProcessError as e:
        log.error("Unable to call Verilator to check version: " + str(e))
        log.error(e.stdout)
        return None


def convert_verible_version(version_string):
    '''Convert Verible version string to semantic versioning format.'''
    # 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_string)

    if m is None:
        log.error("{} has invalid version string format.".format(version_string))
        return None

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


def get_verible_version():
    '''Run Verible to check its version'''
    try:
        version_str = subprocess.run('verible-verilog-lint --version', shell=True,
                                     check=True, stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT,
                                     universal_newlines=True)
        return version_str.stdout.split('\n')[0].strip()

    except subprocess.CalledProcessError as e:
        log.error("Unable to call Verible to check version: " + str(e))
        log.error(e.stdout)
        return None


def pip3_get_version(tool):
    '''Run pip3 to find the version of an installed module'''
    cmd = ['pip3', 'show', tool]
    try:
        proc = subprocess.run(cmd,
                              check=True,
                              stderr=subprocess.STDOUT,
                              stdout=subprocess.PIPE,
                              universal_newlines=True)
    except subprocess.CalledProcessError as err:
        log.error('pip3 command failed: {}'.format(err))
        log.error("Failed to get version of {} with pip3: is it installed?"
                  .format(tool))
        log.error(err.stdout)
        return None

    version_re = 'Version: (.*)'
    for line in proc.stdout.splitlines():
        match = re.match(version_re, line)
        if match:
            return match.group(1)

    # If we get here, we never saw a version line.
    log.error('No output line from running {} started with "Version: ".'
              .format(cmd))
    return None


def check_version(requirements, tool_name, getter, version_converter=None):
    required_version = requirements.get(tool_name)
    if required_version is None:
        log.error('Requirements file does not specify version for {}.'
                  .format(tool_name))
        return False

    actual_version = getter()
    if actual_version is None:
        return False

    # If a version string converter is defined, call it. This is required
    # for some version strings that are not compatible with StrictVersion.
    if version_converter is not None:
        required_version = version_converter(required_version)
        actual_version = version_converter(actual_version)

    if StrictVersion(actual_version) < StrictVersion(required_version):
        log.error("%s is too old: found version %s, need at least %s",
                  tool_name, actual_version, required_version)
        return False
    else:
        log.info("Found sufficiently recent version of %s (found %s, need %s)",
                 tool_name, actual_version, required_version)
        return True


def main():
    # Get tool requirements
    tool_requirements = read_tool_requirements()
    if tool_requirements is None:
        return 1

    all_good = True
    all_good &= check_version(tool_requirements,
                              'verilator',
                              get_verilator_version)
    all_good &= check_version(tool_requirements,
                              'verible',
                              get_verible_version,
                              convert_verible_version)
    all_good &= check_version(tool_requirements,
                              'edalize',
                              lambda: pip3_get_version('edalize'))

    if not all_good:
        log.error("Tool requirements not fulfilled. "
                  "Please update the tools and retry.")
        return 1

    return 0


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