#!/usr/bin/env python3

"""Run templatisation on a template name or file

`CreoleCat` support two modes:

  - run on a template name with option -t: the name is looked up in
    ``/usr/share/eole/creole/distrib/``. The output files are
    calculated unless you explicitely specify ``-o``.

  - run on a file with options -s: this mode requires the use of
    ``-o`` option.

"""

import sys
import os
import argparse

from os.path import basename, join, split, dirname, isdir

from pyeole import scriptargs
from pyeole.log import init_logging

from creole.template import CreoleTemplateEngine, find_files
import creole.config as cfg
from creole.client import CreoleClient, CreoleClientError
from pyeole.ihm import only_root

only_root()

client = CreoleClient()

def parse_cmdline():
    """Parse commande line.
    """
    parser = argparse.ArgumentParser(description="Instancie un template creole",
                                     parents=[scriptargs.container(),
                                              scriptargs.logging()])
    parser.add_argument("-t", "--template", metavar="NAME",
                  help="nom du fichier template creole présent "
                  "dans /usr/share/eole/creole/distrib")
    parser.add_argument("-s", "--source", metavar="PATH",
                  help="chemin d’un fichier template")
    parser.add_argument("-f", "--filename", metavar="FILENAME",
                  help="destination du template creole présent")
    parser.add_argument("-o", "--output", metavar="OUTPUTFILE",
                  help="chemin du fichier généré")

    opts = parser.parse_args()
    exclusive_options = ["source", "template", "filename"]
    opt_sources = [option for option in exclusive_options if getattr(opts, option) is not None]

    if ( len(opt_sources) == 0 or len(opt_sources) >= 2 ):
        parser.error("Vous devez spécifier une des options"
                     "'--template' ou '--source' ou '--filename'.")

    if opts.source is not None and not os.access(opts.source, os.F_OK):
        parser.error("Fichier source inexistant"
                     " ou illisible: {0}".format(opts.source))

    if opts.filename is not None and not isdir(dirname(opts.filename)):
        parser.error("Répertoire de destination inexistant".format(opts.filename))

    if opts.filename is not None and opts.output is not None:
        parser.error("L'option output n'est pas compatible avec l'option filename".format(opts.filename))

    if opts.output is None:
        if opts.source is not None:
            opts.output = ""
    else:
        if opts.template is not None \
           and opts.output == join(cfg.distrib_dir, opts.template):
            parser.error("Le fichier de sortie ne peut écraser"
                         " le fichier template: {0}".format(opts.output) )
        if opts.source is not None and opts.output == opts.source:
            parser.error("Le fichier de sortie ne peut écraser"
                         " le fichier source: {0}".format(opts.output) )

    if opts.verbose:
        opts.log_level = 'info'
    if opts.debug:
        opts.log_level = 'debug'

    return opts


def main():
    """Setup environnment and run templatisation.
    """

    options = parse_cmdline()
    try:
        log = init_logging(level=options.log_level)

        engine = CreoleTemplateEngine()

        filevar = { 'source': options.source,
                    'name': options.output,
                    'full_name': options.output,
                    'filename': options.filename,
                    'activate' : True,
                    'del_comment': '',
                    'mkdir' : False,
                    'rm' : False,
        }


        if options.container is not None:
            # force container context
            groups = [client.get_container_infos(options.container)]
        elif options.output is not None:
            # Source without container, for root context
            groups = [client.get_container_infos('root')]
        else:
            groups = []
            for group in client.get_groups():
                groups.append(client.get_group_infos(group))

        instanciated_files = []
        for group in groups:
            if filevar['source'] is not None:
                instanciated_files.append(filevar)
                engine.process(filevar, group)
            elif filevar['filename'] is not None:
                instanciated_files.append(filevar)
                engine.instance_file(filename=filevar['filename'], container=options.container or 'root')
            elif options.template is not None:
                for found_file in find_files(options.template, client, group):
                    instanciated_files.append(found_file)
                    if options.output is None:
                        engine._instance_file(found_file, group)
                    else:
                        # Override output
                        found_file['name'] = options.output
                        found_file['full_name'] = options.output
                        # Do not get through verify and
                        # change_properties
                        engine._copy_to_template_dir(found_file)
                        engine.process(found_file, group)

        if not instanciated_files:
            # No file get instanciated
            raise CreoleClientError("Fichier template inexistant:"
                                    " {0}".format(options.template))

    except Exception as err:
        if options.debug:
            log.debug(err, exc_info=True)
        else:
            log.error(err)
        sys.exit(1)
    sys.exit(0)

if __name__ == '__main__':
    main()
