#!python
"""
Easy conversion of data from different formats to other formats.
"""
from __future__ import print_function, division

import sys, os, os.path as osp
import argparse as arg

import sisl

def argparse_patch(parser):
    """ Patch the argparse module such that one may process the Namespace in subparsers

    This patch have been created by: 
      paul.j3 (http://bugs.python.org/file44363/issue27859test.py)
    and adapted by Nick R. Papior with minor edits.

    Parameters
    ----------
    parser: ArgumentParser
       parser to be patched
    """
    class MySubParsersAction(arg._SubParsersAction):
        def __call__(self, parser, namespace, values, option_string=None):
            parser_name = values[0]
            arg_strings = values[1:]

            # set the parser name if requested
            if self.dest is not argparse.SUPPRESS:
                setattr(namespace, self.dest, parser_name)

            # select the parser
            try:
                parser = self._name_parser_map[parser_name]
            except KeyError:
                args = {'parser_name': parser_name,
                        'choices': ', '.join(self._name_parser_map)}
                msg = _('unknown parser %(parser_name)r (choices: %(choices)s)') % args
                raise ArgumentError(self, msg)

            # parse all the remaining options into the namespace
            # store any unrecognized options on the object, so that the top
            # level parser can decide what to do with them

            # pass parent namespace (it is now the users responsibility to
            # not have dublicate .default parameters)
            namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)

            ## ORIGINAL
            #subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
            #for key, value in vars(subnamespace).items():
            #    setattr(namespace, key, value)

            if arg_strings:
                vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
                getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
    parser.register('action', 'parsers', MySubParsersAction)


def run():

    # The file *MUST* be the first argument
    # (except --help|-h)

    # We cannot create a separate ArgumentParser to retrieve a positional arguments
    # as that will grab the first argument for an option!

    # Start creating the command-line utilities that are the actual ones.
    description = """
This manipulation utility can handle nearly all files in the sisl code in
changing ways. It handles files dependent on type AND content.
    """.format(osp.basename(sys.argv[0]))

    if len(sys.argv) == 1:
        # no arguments
        # fake a help
        argv = ['--help']
    else:
        argv = sys.argv[1:]


    obj = None
    input_file = None
    if len(argv) >= 1:
        # Get the file
        input_file = argv[0]

        if osp.isfile(input_file):
            obj = sisl.get_sile(input_file)
            argv.pop(0)
        elif ('-h' in argv) or ('--help' in argv):
            # Fake help...
            description += """

One *must* supply a file before a help menu can be generated.
The help menu depends on the type of Sile that is specified.
"""
        else:
            # The file that the user request, does not exist
            raise ValueError("File: '"+input_file+"' cannot be found. Please supply a readable file!")

    p = arg.ArgumentParser("Manipulates sisl Sile's for manipulation.",
                           formatter_class=arg.RawDescriptionHelpFormatter,
                           description=description)
    
    # Patch the parser to allow namespace passing in subparsers...
    argparse_patch(p)

    # We are good to go!!!

    # Append the geometry arguments from the object
    if not obj is None:
        p, namespace = obj.ArgumentParser(p, **obj._ArgumentParser_args_single())
    else:
        namespace = sisl.utils.default_namespace()
    
    # Be sure to add the input file
    setattr(namespace, '_input_file', input_file)

    args = p.parse_args(argv, namespace=namespace)


if __name__ == "__main__":
    run()
