############################################################################
# tools/pynuttx/nxgdb/uname.py
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.  The
# ASF licenses this file to you 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.
#
############################################################################

import argparse
import subprocess
from os import path

import gdb

from . import autocompeletion, utils


def get_commit_id():
    here = path.dirname(path.abspath(__file__))
    try:
        result = subprocess.run(
            ["git", "-C", here, "rev-parse", "--short", "HEAD"],
            check=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.DEVNULL,
            text=True,
        )
        return result.stdout.strip()
    except (subprocess.CalledProcessError, FileNotFoundError):
        return "unknown"


def get_symbol_string(symbol):
    sym = utils.get_static_var(symbol)
    if not sym or not sym.value():
        return ""

    return sym.value().string()


kernel_name = "NuttX"
node_name = get_symbol_string("g_hostname")
kernel_release = get_symbol_string("g_release")
kernel_version = get_symbol_string("g_version")
machine = get_symbol_string("g_arch")
tool_version = get_commit_id()


@autocompeletion.complete
class UnameCommand(gdb.Command):
    """Output specific system information"""

    def get_argparser(self):
        parser = argparse.ArgumentParser(description=self.__doc__)
        parser.add_argument(
            "-a",
            "--all",
            action="store_true",
            help="Output all information in the following order",
        )
        parser.add_argument(
            "-s", "--kernel-name", action="store_true", help="Output the kernel name"
        )
        parser.add_argument(
            "-n",
            "--nodename",
            action="store_true",
            help="Output the hostname of the network node",
        )
        parser.add_argument(
            "-r",
            "--kernel-release",
            action="store_true",
            help="Output the kernel release number",
        )
        parser.add_argument(
            "-v",
            "--kernel-version",
            action="store_true",
            help="Output the kernel version number",
        )
        parser.add_argument(
            "-m",
            "--machine",
            action="store_true",
            help="Output the hardware architecture name of the host",
        )
        parser.add_argument(
            "--version",
            action="store_true",
            help="Display version information and exit",
        )
        return parser

    def __init__(self):
        super().__init__("uname", gdb.COMMAND_USER)
        self.parser = self.get_argparser()

    def parse_arguments(self, argv):
        try:
            args = self.parser.parse_args(argv)
        except SystemExit:
            return None

        return args

    @utils.dont_repeat_decorator
    def invoke(self, args, from_tty):
        args = self.parse_arguments(gdb.string_to_argv(args))
        if not args:
            return

        if args.all:
            print(
                kernel_name,
                node_name,
                kernel_release,
                kernel_version,
                machine,
                tool_version,
            )
            return
        if args.kernel_name:
            print(kernel_name)
        if args.nodename:
            print(node_name)
        if args.kernel_release:
            print(kernel_release)
        if args.kernel_version:
            print(kernel_version)
        if args.machine:
            print(machine)
        if args.version:
            print(tool_version)

    def diagnose(self, *args, **kwargs):
        return {
            "title": "Uname Report",
            "summary": "Version numbers of both tool and kernel",
            "command": "uname",
            "result": "info",
            "category": utils.DiagnoseCategory.system,
            "message": gdb.execute("uname -a", to_string=True),
        }
