"""
Takes a list of server/class/devices (optionally with wildcards)
and prints the current configuration for those in JSON dsconfig format.

$ python -m dsconfig.dump server:TangoTest/1 > result.json
$ python -m dsconfig.dump device:sys/tg_test/1 device:sys/tg_test/2
...

"""

from collections import defaultdict
import tango

from .appending_dict import merge
from .tangodb import get_servers_with_filters, get_classes_properties


def get_db_data(
    db, patterns=None, class_properties=False, include_tango_host=True, **options
):
    # dump TANGO database into JSON. Optionally filter which things to include
    # (currently only "positive" filters are possible; you can say which
    # servers/classes/devices to include, but you can't exclude selectively)
    # By default, dserver devices aren't included!

    data = defaultdict(dict)

    if include_tango_host:
        tango_host = tango.ApiUtil.get_env_var("TANGO_HOST")
        if tango_host:
            data["tango_host"] = tango_host

    if not patterns:
        # the user did not specify a pattern, so we will dump *everything*
        servers = get_servers_with_filters(db, **options).to_dict()
        data["servers"].update(servers)
        if class_properties:
            classes = get_classes_properties(db).to_dict()
            data["classes"].update(classes)
    else:
        # go through all patterns and fill in the data
        for pattern in patterns:
            prefix, pattern = pattern.split(":")
            if prefix == "class":
                prefix = "clss"
            kwargs = {prefix: pattern}
            kwargs.update(options)
            servers = get_servers_with_filters(db, **kwargs).to_dict()
            merge(data["servers"], servers)
            if class_properties:
                # Get the relevant class properties
                if prefix == "server":
                    classes = get_classes_properties(db, server=pattern).to_dict()
                elif prefix == "clss":
                    classes = get_classes_properties(db, clss=pattern).to_dict()
                elif prefix == "device":
                    classes = get_classes_properties(db, device=pattern).to_dict()
                merge(data["classes"], classes)
    return dict(data)


def main():
    import json
    from argparse import ArgumentParser

    usage = r"Usage: tango2json [term:pattern term2:pattern2...]"
    parser = ArgumentParser(usage=usage)
    parser.add_argument(
        "filter",
        nargs="*",
        help=(
            "Include only things matching a filter."
            + " E.g. 'device:sys/tg_test/1', 'class:Database'"
            + " Multiple filters are allowed."
        ),
    )
    parser.add_argument(
        "-p",
        "--no-properties",
        dest="properties",
        action="store_false",
        default=True,
        help="Exclude device properties",
    )
    parser.add_argument(
        "-a",
        "--no-attribute-properties",
        dest="attribute_properties",
        action="store_false",
        default=True,
        help="Exclude attribute properties",
    )
    parser.add_argument(
        "-l",
        "--no-aliases",
        dest="aliases",
        action="store_false",
        default=True,
        help="Exclude device aliases",
    )
    parser.add_argument(
        "-d",
        "--dservers",
        dest="dservers",
        action="store_true",
        help="Include DServer devices",
    )
    parser.add_argument(
        "-s",
        "--subdevices",
        dest="subdevices",
        action="store_true",
        default=False,
        help="Include __SubDevices property",
    )
    parser.add_argument(
        "-c",
        "--class-properties",
        dest="class_properties",
        action="store_true",
        default=False,
        help="Include class properties",
    )
    parser.add_argument(
        "-t",
        "--exclude-tango-host",
        action="store_true",
        default=False,
        help="Include TANGO_HOST",
    )

    args = parser.parse_args()

    db = tango.Database()
    dbdata = get_db_data(
        db,
        args.filter,
        properties=args.properties,
        class_properties=args.class_properties,
        attribute_properties=args.attribute_properties,
        aliases=args.aliases,
        dservers=args.dservers,
        subdevices=args.subdevices,
        include_tango_host=not args.exclude_tango_host,
    )
    print(json.dumps(dbdata, ensure_ascii=False, indent=4, sort_keys=True))


if __name__ == "__main__":
    main()
