#!/usr/bin/env python3
"""
Creates files for a given attribute present in the database

Usage:
  fastsubtrees-attributes-construct [options] <outfile> <tree> <attribute>
                                              <attrmod> [<attrmod_data>...]

Arguments:
  outfile       desired name for the output file
  tree          fastsubtrees tree representation file,
                e.g. output by fastsubtrees-construct
  attribute     name of the attribute
  attrmod       Python module defining a function attribute_values()
                which may take arguments (<attrmod_data>) and returns pairs
                (element_id, attribute_value) for each node to which an
                attribute value exists.
  attrmod_data  [optional] arguments to be passed to the attribute_values()
                function of the module specified as <attrmod>; to pass keyword
                arguments, use the syntax "key=value" and the option --keyargs

Options:
  --keyargs    split the arguments specified in <idsmod_data> into
               keywords and values by splitting on the first instance of '=';
               arguments which do not contain '=' are passed as positional,
               before any keyword argument
  --quiet      disable log messages
  --debug      print debug information
  --help       show this help message and exit
  --version    show program's version number and exit
"""

from docopt import docopt
from fastsubtrees import _scripts_support, logger, Tree
import importlib
import json
from pathlib import Path

def main(args):
  logger.debug("Loading Python module '{}'".format(args['<attrmod>']))
  modulename = Path(args["<attrmod>"]).stem
  spec = importlib.util.spec_from_file_location(modulename, args["<attrmod>"])
  m = importlib.util.module_from_spec(spec)
  spec.loader.exec_module(m)
  if not m.__dict__.get("attribute_values"):
    raise ValueError("The specified Python module {} does not define a "
                     "function attribute_values()".format(args["<attrmod>"]))
  logger.success("Attributes module loaded, found generator attribute_values()")
  if args["--keyargs"]:
    keyargs = {k: v for k, v in \
               [a.split("=", 1) for a in args["<attrmod_data>"] if "=" in a]}
    posargs = [a for a in args["<attrmod_data>"] if "=" not in a]
  else:
    keyargs = {}
    posargs = args["<attrmod_data>"]
  if posargs:
    logger.debug(f"Positional arguments passed to the generator: {posargs}")
  if keyargs:
    logger.debug(f"Keyword arguments passed to the generator: {keyargs}")
  logger.debug("Loading tree from file '{}'".format(args['<tree>']))
  tree = Tree.from_file(args["<tree>"])
  elementid_attributes_dictionary = m.attribute_values(args["<attribute>"], *posargs, **keyargs)
  filename = args["<outfile>"]
  logger.debug("Writing attribute values to file '{}'".format(args['<outfile>']))
  with open(filename, "w") as outfile:
    for element_id in tree.subtree_ids(tree.root_id):
      attribute = elementid_attributes_dictionary.get(element_id, None)
      outfile.write(json.dumps(attribute) + "\n")
  logger.success("Attribute values successfully written to file '{}'".format(args['<outfile>']))

if __name__ == "__main__":
  args = docopt(__doc__, version="0.1")
  _scripts_support.setup_verbosity(args)
  main(args)
