#!/usr/bin/python3.13
# -*- coding: utf-8 -*-

# Copyright 2004-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

from java_config_2.OutputFormatter import OutputFormatter
from java_config_2.EnvironmentManager import EnvironmentManager
from java_config_2.Errors import *

import os
import sys
try:
    # Python 3.
    from subprocess import getoutput
except ImportError:
    # Python 2.
    from commands import getoutput

from optparse import OptionParser, OptionGroup

def version(option, opt, value, parser):
    import java_config_2
    printer._print(f"%H%BJava Configuration Utility %GVersion {java_config_2.version}")
    raise SystemExit()

def nocolor(option, opt, value, parser):
    printer.setColorOutputStatus(False)

def get_command(command):
    try:
        printer._print(manager.get_active_vm().find_exec(command))
    except PermissionError:
        fatalError("The " + command + " executable was not found in the Java path")

def java(option, opt, value, parser):
    get_command('java')

def javac(option, opt, value, parser):
    get_command('javac')

def jar(option, opt, value, parser):
    get_command('jar')

def query_active_vm(var):
    try:
        printer._print(manager.get_active_vm().query(var))
    except EnvironmentUndefinedError:
        fatalError("%s could not be found in the active VM environment" % var)

def query_active_vm_cb(option, opt, value, parse, *args):
    return query_active_vm(args[0])

def tools(option, opt, value, parser):
    jh = ''
    try:
        jh = manager.get_active_vm().query('JAVA_HOME')
    except EnvironmentUndefinedError:
        fatalError("JAVA_HOME not found in the active VM environment")
    tools_jar = jh + '/lib/tools.jar'
    if not os.path.exists(tools_jar):
        sys.exit(1);
    printer._print(tools_jar)

def show_active_vm(option, opt, value, parser):
    printer._print(manager.get_active_vm().name())

def java_version(option, opt, value, parser):
    try:
        printer._print(getoutput('%s -version' % manager.get_active_vm().find_exec('java')))
    except PermissionError:
        fatalError("The java executable was not found in the Java path")

def query_pkg_path(option, opt, value, parser, query):
    error = False
    try:
        packages = value.split(',')
        missing_deps = set()
        if not parser.values.with_deps:
            path = manager.build_path(packages, query)
        else:
            path = manager.build_dep_path(packages, query, missing_deps)

        printer._print(':'.join(path))

        if len(missing_deps) > 0:
            for dep in missing_deps:
                printer._printError("Dependency package %s was not found!" % dep)
            error = True

    except UnexistingPackageError as e:
        printer._printError("Package %s was not found!" % e.package)
        error = True

    if error:
        sys.exit(1)

def query_pkg(option, opt, value, parser):
    error = False
    query = parser.values.query
    if query:
        try:
            package = manager.get_package(value)
            if package.query(query):
                printer._print(package.query(query))
            else:
                printer._printError('Package %s does not define %s in it\'s package.env.' % (package.name(), query))
        except UnexistingPackageError as e:
            printer._printError("Package %s was not found!" % e.package)
        except PermissionError as e:
            printer._printError("You do not have enough permissions to read the package's package.env")
            error = True
    else:
        printer._printError("No query parameter was specified, unable to retrieve package.env value.")
        error = True

    if error:
        sys.exit(1)

def get_virtual_providers( option, opt, value, parser):
    if not manager.get_virtual(value):
        printer._printError("Virtual package %s was not found" % value)
        sys.exit(1)

    output = manager.get_virtual(value).get_packages()
    printer._print(','.join(output))

def get_env(option, opt, value, parser):
    for env in value.split(','):
        query_active_vm(env)

def exec_cmd(option, opt, value, parser):
    for cmd in iter(value.split(',')):
        os.system(cmd)

def list_available_packages(option, opt, value, parser):
    for package in manager.get_packages().values():
        printer._print("[%s] %s (%s)" % (package.name(), package.description(), package.file()))

def list_available_vms(option, opt, value, parser):
    vm_list = manager.get_virtual_machines()
    try:
        active = manager.get_active_vm()
    except InvalidVMError:
        active = None

    found_build_only = False
    printer._print('%HThe following VMs are available for generation-2:%$')
    for i, vm in vm_list.items():
        if vm is active:
            if not vm.is_build_only():
                printer._print('%G' + '*)\t%s [%s]%s' % (vm.query('VERSION'), vm.name(), '%$'))
            else:
                printer._print('%G' + '*)\t%s [%s]%s' % (vm.query('VERSION'), vm.name(), '%$') + '%r (Build Only)%$')
                found_build_only = True
        else:
            if not vm.is_build_only():
                printer._print('%i)\t%s [%s]' % (i, vm.query('VERSION'), vm.name()))
            else:
                printer._print('%i)\t%s [%s]' % (i, vm.query('VERSION'), vm.name()) + '%r (Build Only)%$')
                found_build_only = True

    if found_build_only:
        printer._print('')
        printer._print('%r' + 'VMs marked as Build Only may contain Security Vulnerabilities and/or be EOL.')
        printer._print('%r' + 'Gentoo recommends not setting these VMs as either your System or User VM.')

def print_environment(option, opt, value, parser):
    vm = manager.get_vm(value) 
    if not vm:
        fatalError("Could not find a vm matching: %s" % value)
    manager.create_env_entry(vm, printer, "%s=%s")

def select_vm(option, opt, value, parser):
    if not value: return
    vm = manager.get_vm(value)
    if not vm:
        fatalError("The vm could not be found")
    manager.set_active_vm(manager.get_vm(value))

def fatalError(msg):
    printer._printError(msg)
    sys.exit(1)

if __name__ == '__main__':
    global printer, manager
    import java_config_2
    printer = OutputFormatter(True, True)
    manager = EnvironmentManager(os.getenv('ROOT', ''), java_config_2.eprefix)

    usage = f"""java-config [options]
Java Configuration Utility Version {java_config_2.version}
Copyright 2004-2024 Gentoo Authors
Distributed under the terms of the GNU General Public License v2
Please contact the Gentoo Java Project <java@gentoo.org> with problems."""

    parser = OptionParser(usage)
    parser.add_option("-V", "--version",
                    action="callback", callback=version,
                    help="Print version information")
    parser.add_option("--select-vm",
                    action="callback", callback=select_vm,
                    type="string", dest="vm",
                    help="Use this vm instead of the active vm when returning information")
    parser.add_option("-n", "--nocolor",
                    action="callback", callback=nocolor,
                    help="Disable color output")

    # Queries
    group = OptionGroup(parser, "Queries")
    group.add_option("-J", "--java",
                    action="callback", callback=java,
                    help="Print the location of the java executable")
    group.add_option("-c", "--javac",
                    action="callback", callback=javac,
                    help="Print the location of the javac executable")
    group.add_option("-j", "--jar",
                    action="callback", callback=jar,
                    help="Print the location of the jar executable")
    group.add_option("-t", "--tools",
                    action="callback", callback=tools,
                    help="Print the path to tools.jar")
    group.add_option("-f", "--show-active-vm",
                    action="callback", callback=show_active_vm,
                    help="Print the active Virtual Machine")
    group.add_option("-v", "--java-version",
                    action="callback", callback=java_version,
                    help="Print version information for the active VM")
    group.add_option("-g", "--get-env",
                    action="callback", callback=get_env,
                    type="string", dest="var",
                    help="Print an environment variable from the active VM")
    group.add_option("-P", "--print",
                    action="callback", callback=print_environment,
                    type="string", dest="vm",
                    help="Print the environment for the specified VM")
    group.add_option("-e", "--exec_cmd",
                    action="callback", callback=exec_cmd,
                    type="string", dest="command",
                    help="Execute something which is in JAVA_HOME")
    group.add_option("-L", "--list-available-vms",
                    action="callback", callback=list_available_vms,
                    help="List available Java Virtual Machines")
    group.add_option("-l", "--list-available-packages",
                    action="callback", callback=list_available_packages,
                    help="List all available packages on the system.")
    group.add_option("-d", "--with-dependencies",
                    action="store_true",
                    default=False, dest="with_deps",
                    help="Include package dependencies in --classpath and --library calls")
    group.add_option("-p", "--classpath",
                    action="callback", callback=query_pkg_path, callback_args = ("CLASSPATH",),
                    type="string", dest="package(s)",
                    help="Print entries in the environment classpath for these packages")
    group.add_option("--package",
                    action="callback", callback=query_pkg,
                    type="string", dest="package(s)",
                    help="Retrieve a value from a packages package.env file, value is specified by --query")
    group.add_option("-q", "--query",
                    action="store",
                    type="string", dest="query",
                    help="Value to retieve from packages package.env file, specified by --package")
    group.add_option("-i", "--library",
                    action="callback", callback=query_pkg_path, callback_args = ("LIBRARY_PATH",),
                    type="string", dest="package(s)",
                    help="Print java library paths for these packages")
    group.add_option("-r", "--runtime",
                    action="callback", callback=query_active_vm_cb, callback_args=("BOOTCLASSPATH",),
                    help="Print the runtime classpath")
    group.add_option("-O", "--jdk-home",
                    action="callback", callback=query_active_vm_cb, callback_args=("JAVA_HOME",),
                    help="Print the location of the active JAVA_HOME")
    group.add_option("-o", "--jre-home",
                    action="callback", callback=query_active_vm_cb, callback_args=("JAVA_HOME",),
                    help="Print the location of the active JAVA_HOME")
    parser.add_option_group(group)

    # Experimental
    group = OptionGroup(parser, "Experimental")
    group.add_option("--get-virtual-providers",
                    action="callback", callback=get_virtual_providers,
                    type="string", dest="package(s)",
                    help="Return a list of packages that provide a virtual")
    parser.add_option_group(group)

    if len(sys.argv) < 2: 
        parser.print_help()
    else:
        try:
            # Makes sure that --nocolor and --query are always 
            # the first argument(s)
            # because otherwise callbacks before it will output
            # colored output or --query param will not be set for
            # the query_pkg callback

            args = sys.argv[1:]
            for opt in ('-q', '--query'):
                try:
                    args.remove(opt)
                    args.insert(0, opt)
                except ValueError:
                    pass
            args = sys.argv[1:]
            for opt in ( '-n', '--nocolor'):
                try:
                    args.remove(opt)
                    args.insert(0,opt)
                except ValueError:
                    pass

            (options, args) = parser.parse_args(args=args)
        except InvalidVMError:
            fatalError("The active vm could not be found")
        except ProviderUnavailableError as e:
            message = "No providers are available, please ensure you have one of the following VM's or Package's;\n"
            message += "VM's (Your active vm must be one of these): " + e.vms() + "\n"
            message += "Packages's: " + e.packages() + "\n"
            fatalError(message)

# vim:set expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap:
