# -*- Mode: Python -*-
# coding=utf-8

# GDBus - GLib D-Bus Library
#
# Copyright (C) 2008-2011 Red Hat, Inc.
# Copyright (C) 2018 Iñigo Martínez <inigomartinez@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General
# Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
#
# Author: David Zeuthen <davidz@redhat.com>

import argparse
import os
import sys

from . import config
from . import dbustypes
from . import parser
from . import codegen
from . import codegen_docbook
from .utils import print_error, print_warning


def find_arg(arg_list, arg_name):
    for a in arg_list:
        if a.name == arg_name:
            return a
    return None


def find_method(iface, method):
    for m in iface.methods:
        if m.name == method:
            return m
    return None


def find_signal(iface, signal):
    for m in iface.signals:
        if m.name == signal:
            return m
    return None


def find_prop(iface, prop):
    for m in iface.properties:
        if m.name == prop:
            return m
    return None


def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
    iface_obj = None
    for i in iface_list:
        if i.name == iface:
            iface_obj = i
            break

    if iface_obj is None:
        print_error('No interface "{}"'.format(iface))

    target_obj = None

    if method:
        method_obj = find_method(iface_obj, method)
        if method_obj is None:
            print_error('No method "{}" on interface "{}"'.format(method, iface))
        if arg:
            arg_obj = find_arg(method_obj.in_args, arg)
            if arg_obj is None:
                arg_obj = find_arg(method_obj.out_args, arg)
                if arg_obj is None:
                    print_error(
                        'No arg "{}" on method "{}" on interface "{}"'.format(
                            arg, method, iface
                        )
                    )
            target_obj = arg_obj
        else:
            target_obj = method_obj
    elif signal:
        signal_obj = find_signal(iface_obj, signal)
        if signal_obj is None:
            print_error('No signal "{}" on interface "{}"'.format(signal, iface))
        if arg:
            arg_obj = find_arg(signal_obj.args, arg)
            if arg_obj is None:
                print_error(
                    'No arg "{}" on signal "{}" on interface "{}"'.format(
                        arg, signal, iface
                    )
                )
            target_obj = arg_obj
        else:
            target_obj = signal_obj
    elif prop:
        prop_obj = find_prop(iface_obj, prop)
        if prop_obj is None:
            print_error('No property "{}" on interface "{}"'.format(prop, iface))
        target_obj = prop_obj
    else:
        target_obj = iface_obj
    target_obj.annotations.insert(0, dbustypes.Annotation(key, value))


def apply_annotations(iface_list, annotation_list):
    # apply annotations given on the command line
    for (what, key, value) in annotation_list:
        pos = what.find("::")
        if pos != -1:
            # signal
            iface = what[0:pos]
            signal = what[pos + 2 :]
            pos = signal.find("[")
            if pos != -1:
                arg = signal[pos + 1 :]
                signal = signal[0:pos]
                pos = arg.find("]")
                arg = arg[0:pos]
                apply_annotation(iface_list, iface, None, signal, None, arg, key, value)
            else:
                apply_annotation(
                    iface_list, iface, None, signal, None, None, key, value
                )
        else:
            pos = what.find(":")
            if pos != -1:
                # property
                iface = what[0:pos]
                prop = what[pos + 1 :]
                apply_annotation(iface_list, iface, None, None, prop, None, key, value)
            else:
                pos = what.find("()")
                if pos != -1:
                    # method
                    combined = what[0:pos]
                    pos = combined.rfind(".")
                    iface = combined[0:pos]
                    method = combined[pos + 1 :]
                    pos = what.find("[")
                    if pos != -1:
                        arg = what[pos + 1 :]
                        pos = arg.find("]")
                        arg = arg[0:pos]
                        apply_annotation(
                            iface_list, iface, method, None, None, arg, key, value
                        )
                    else:
                        apply_annotation(
                            iface_list, iface, method, None, None, None, key, value
                        )
                else:
                    # must be an interface
                    iface = what
                    apply_annotation(
                        iface_list, iface, None, None, None, None, key, value
                    )


def codegen_main():
    arg_parser = argparse.ArgumentParser(
        description="D-Bus code and documentation generator"
    )
    arg_parser.add_argument(
        "files", metavar="FILE", nargs="+", help="D-Bus introspection XML file"
    )
    arg_parser.add_argument(
        "--xml-files",
        metavar="FILE",
        action="append",
        default=[],
        help=argparse.SUPPRESS,
    )
    arg_parser.add_argument(
        "--interface-prefix",
        metavar="PREFIX",
        default="",
        help="String to strip from D-Bus interface names for code and docs",
    )
    arg_parser.add_argument(
        "--c-namespace",
        metavar="NAMESPACE",
        default="",
        help="The namespace to use for generated C code",
    )
    arg_parser.add_argument(
        "--c-generate-object-manager",
        action="store_true",
        help="Generate a GDBusObjectManagerClient subclass when generating C code",
    )
    arg_parser.add_argument(
        "--c-generate-autocleanup",
        choices=["none", "objects", "all"],
        default="objects",
        help="Generate autocleanup support",
    )
    arg_parser.add_argument(
        "--generate-docbook",
        metavar="OUTFILES",
        help="Generate Docbook in OUTFILES-org.Project.IFace.xml",
    )
    arg_parser.add_argument(
        "--pragma-once",
        action="store_true",
        help='Use "pragma once" as the inclusion guard',
    )
    arg_parser.add_argument(
        "--annotate",
        nargs=3,
        action="append",
        metavar="WHAT KEY VALUE",
        help="Add annotation (may be used several times)",
    )
    arg_parser.add_argument(
        "--glib-min-required",
        metavar="VERSION",
        help="Minimum version of GLib to be supported by the outputted code "
        "(default: 2.30)",
    )
    arg_parser.add_argument(
        "--glib-max-allowed",
        metavar="VERSION",
        help="Maximum version of GLib to be used by the outputted code "
        "(default: current GLib version)",
    )
    arg_parser.add_argument(
        "--symbol-decorator",
        help="Macro used to decorate a symbol in the outputted header, "
        "possibly to export symbols",
    )
    arg_parser.add_argument(
        "--symbol-decorator-header",
        help="Additional header required for decorator specified by "
        "--symbol-decorator",
    )
    arg_parser.add_argument(
        "--symbol-decorator-define",
        help="Additional define required for decorator specified by "
        "--symbol-decorator",
    )

    group = arg_parser.add_mutually_exclusive_group()
    group.add_argument(
        "--generate-c-code", metavar="OUTFILES", help="Generate C code in OUTFILES.[ch]"
    )
    group.add_argument("--header", action="store_true", help="Generate C headers")
    group.add_argument("--body", action="store_true", help="Generate C code")
    group.add_argument(
        "--interface-info-header",
        action="store_true",
        help="Generate GDBusInterfaceInfo C header",
    )
    group.add_argument(
        "--interface-info-body",
        action="store_true",
        help="Generate GDBusInterfaceInfo C code",
    )

    group = arg_parser.add_mutually_exclusive_group()
    group.add_argument(
        "--output", metavar="FILE", help="Write output into the specified file"
    )
    group.add_argument(
        "--output-directory",
        metavar="OUTDIR",
        default="",
        help="Location to output generated files",
    )

    args = arg_parser.parse_args()

    if len(args.xml_files) > 0:
        print_warning(
            'The "--xml-files" option is deprecated; use positional arguments instead'
        )

    if (
        args.generate_c_code is not None or args.generate_docbook is not None
    ) and args.output is not None:
        print_error(
            "Using --generate-c-code or --generate-docbook and "
            "--output at the same time is not allowed"
        )

    if args.generate_c_code:
        header_name = args.generate_c_code + ".h"
        h_file = os.path.join(args.output_directory, header_name)
        args.header = True
        c_file = os.path.join(args.output_directory, args.generate_c_code + ".c")
        args.body = True
    elif args.header:
        if args.output is None:
            print_error("Using --header requires --output")

        h_file = args.output
        header_name = os.path.basename(h_file)
    elif args.body:
        if args.output is None:
            print_error("Using --body requires --output")

        c_file = args.output
        header_name = os.path.splitext(os.path.basename(c_file))[0] + ".h"
    elif args.interface_info_header:
        if args.output is None:
            print_error("Using --interface-info-header requires --output")
        if args.c_generate_object_manager:
            print_error(
                "--c-generate-object-manager is incompatible with "
                "--interface-info-header"
            )

        h_file = args.output
        header_name = os.path.basename(h_file)
    elif args.interface_info_body:
        if args.output is None:
            print_error("Using --interface-info-body requires --output")
        if args.c_generate_object_manager:
            print_error(
                "--c-generate-object-manager is incompatible with "
                "--interface-info-body"
            )

        c_file = args.output
        header_name = os.path.splitext(os.path.basename(c_file))[0] + ".h"

    # Check the minimum GLib version. The minimum --glib-min-required is 2.30,
    # because that’s when gdbus-codegen was introduced. Support 1, 2 or 3
    # component versions, but ignore the micro component if it’s present.
    if args.glib_min_required:
        try:
            parts = args.glib_min_required.split(".", 3)
            glib_min_required = (int(parts[0]), int(parts[1] if len(parts) > 1 else 0))
            # Ignore micro component, but still validate it:
            _ = int(parts[2] if len(parts) > 2 else 0)  # noqa: F841
        except (ValueError, IndexError):
            print_error(
                "Unrecognized --glib-min-required string ‘{}’".format(
                    args.glib_min_required
                )
            )

        if glib_min_required < (2, 30):
            print_error(
                "Invalid --glib-min-required string ‘{}’: minimum "
                "version is 2.30".format(args.glib_min_required)
            )
    else:
        glib_min_required = (2, 30)

    # And the maximum GLib version.
    if args.glib_max_allowed:
        try:
            parts = args.glib_max_allowed.split(".", 3)
            glib_max_allowed = (int(parts[0]), int(parts[1] if len(parts) > 1 else 0))
            # Ignore micro component, but still validate it:
            _ = int(parts[2] if len(parts) > 2 else 0)  # noqa: F841
        except (ValueError, IndexError):
            print_error(
                "Unrecognized --glib-max-allowed string ‘{}’".format(
                    args.glib_max_allowed
                )
            )
    else:
        glib_max_allowed = (config.MAJOR_VERSION, config.MINOR_VERSION)

    # Only allow --symbol-decorator-define and --symbol-decorator-header if
    # --symbol-decorator is used
    if args.symbol_decorator is None:
        if args.symbol_decorator_header or args.symbol_decorator_define:
            print_error(
                "--symbol-decorator-define and --symbol-decorator-header must "
                "be used with --symbol-decorator"
            )

    # Round --glib-max-allowed up to the next stable release.
    glib_max_allowed = (
        glib_max_allowed[0],
        glib_max_allowed[1] + (glib_max_allowed[1] % 2),
    )

    if glib_max_allowed < glib_min_required:
        print_error(
            "Invalid versions: --glib-min-required ({}) must be "
            "less than or equal to --glib-max-allowed ({})".format(
                glib_min_required, glib_max_allowed
            )
        )

    all_ifaces = []
    input_files_basenames = []
    for fname in sorted(args.files + args.xml_files):
        with open(fname, "rb") as f:
            xml_data = f.read()
        parsed_ifaces = parser.parse_dbus_xml(
            xml_data, h_type_implies_unix_fd=(glib_min_required >= (2, 64))
        )
        all_ifaces.extend(parsed_ifaces)
        input_files_basenames.append(os.path.basename(fname))

    if args.annotate is not None:
        apply_annotations(all_ifaces, args.annotate)

    for i in all_ifaces:
        i.post_process(args.interface_prefix, args.c_namespace)

    docbook = args.generate_docbook
    docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces)
    if docbook:
        docbook_gen.generate(docbook, args.output_directory)

    if args.header:
        with open(h_file, "w") as outfile:
            gen = codegen.HeaderCodeGenerator(
                all_ifaces,
                args.c_namespace,
                args.c_generate_object_manager,
                args.c_generate_autocleanup,
                header_name,
                input_files_basenames,
                args.pragma_once,
                glib_min_required,
                args.symbol_decorator,
                args.symbol_decorator_header,
                outfile,
            )
            gen.generate()

    if args.body:
        with open(c_file, "w") as outfile:
            gen = codegen.CodeGenerator(
                all_ifaces,
                args.c_namespace,
                args.c_generate_object_manager,
                header_name,
                input_files_basenames,
                docbook_gen,
                glib_min_required,
                args.symbol_decorator_define,
                outfile,
            )
            gen.generate()

    if args.interface_info_header:
        with open(h_file, "w") as outfile:
            gen = codegen.InterfaceInfoHeaderCodeGenerator(
                all_ifaces,
                args.c_namespace,
                header_name,
                input_files_basenames,
                args.pragma_once,
                glib_min_required,
                args.symbol_decorator,
                args.symbol_decorator_header,
                outfile,
            )
            gen.generate()

    if args.interface_info_body:
        with open(c_file, "w") as outfile:
            gen = codegen.InterfaceInfoBodyCodeGenerator(
                all_ifaces,
                args.c_namespace,
                header_name,
                input_files_basenames,
                glib_min_required,
                args.symbol_decorator_define,
                outfile,
            )
            gen.generate()

    sys.exit(0)


if __name__ == "__main__":
    codegen_main()
