#!/usr/bin/python
import argparse
import pprint
import json
import os

from pych.version import APP_NAME, APP_VERSION
from pych.compiler import moduralize
from pych import CONFIG

#
# Helper functions for printing output form the pych command
# we do not want to use the logging module since that would
# mess with the configured output of the pych module.
#
def info(msg):
    """
    Print out a information message...
    :param msg str: The message to print.
    """
    print(msg)

def warn(msg):
    """
    Print out a warning message...
    :param msg str: The warning message to print.
    """
    print("WARN: %s" % msg)

def error(msg):
    """
    Print out an error message...
    :param msg str: The error message to print.
    """
    print("ERR: %s" % msg)

#
# pych commands
#
def check(arg):
    """Sanity checks the configuration."""

    info("Checking installation...")

    if not CONFIG:
        error("Cannot find configuration file (pych.json).")

    info(" * Templates")
    for slang in CONFIG["specializers"]["templates"]:
        for template_dir in CONFIG["specializers"]["templates"][slang]:
            if not os.path.exists(template_dir):
                error(
                    "Missing template dir(%s) for slang(%s)",
                    template_dir,
                    slang
                )

    info(" * Object Storage")
    try:
        for slang in CONFIG["object_store"]["output_paths"]:
            o_path = CONFIG["object_store"]["output_paths"][slang]
            path = os.sep.join([
                CONFIG["object_store"]["root_path"],
                o_path,
                'write_test'
            ])
            with open(path, 'w') as fd:
                fd.write("test")
    except Exception as e:
        error("Error trying to write to object-store: %s", e)

    # Check that Chapel libraries are there
    info(" * Libraries")

    # Check that c-headers are there
    info(" * Headers")

    # Check that the commands are invokable
    info(" * Commands")

def version(arg):
    """Print the pyChapel version."""

    info("%s %s" % (APP_NAME, APP_VERSION))

def compile(sfile):
    """Compile a Chapel module into a Python module."""

    if not CONFIG:
        error("Configuration is broken, can't compile.")
        return

    info("Compile this %s" % sfile)
    (source_file, output_file, wrap_fp) = moduralize(sfile)
    info("Compiled sfile(%s) into output_file(%s)"
         " with wrapped-source(%s)" % (
        source_file, output_file, wrap_fp
    ))

def list_bfiles(arg):

    if not CONFIG:
        error("Configuration is broken, can't compile.")
        return

    # TODO: List all the bfiles

def list_sfiles(arg):

    if not CONFIG:
        error("Configuration is broken, can't compile.")
        return

    # TODO: List all the sfiles

def list_store(arg):

    if not CONFIG:
        error("Configuration is broken, can't compile.")
        return

    # TODO: List all the bfiles

def list_templates(arg):

    if not CONFIG:
        error("Configuration is broken, can't compile.")
        return

    # TODO: List all templates

if __name__ == "__main__":

    parser = argparse.ArgumentParser(   # Setup cli-argument parser
        description='Tool aiding the Python/Chapel (pyChapel)  module'
    )
    parser.add_argument(
        '--compile',
        metavar="source_file",
        type=str,
        help='Compile the given Chapel module into a Python module.'
    )
    parser.add_argument(
        '--check',
        action="store_const",
        const=True,
        default=False,
        help="Check the pyChapel installation / configuration"
    )
    parser.add_argument(
        '--version',
        action="store_const",
        const=True,
        default=False,
        help="Print version"
    )
    args = parser.parse_args()

    commands = {                        # Dispatch of 'pych' commands
        'compile': compile,
        'version': version,
        'check': check
    }
    
    exec_command = None                 # Grab a single command
    for command in commands:
        if args.__dict__[command] and not exec_command:
            exec_command = (command, commands[command], args.__dict__[command])
        elif args.__dict__[command] and exec_command:
            warn("One command at a time, ignoring --%s." % (command))

    if exec_command:                    # Invoke it
        cmd_name, cmd, cmd_arg = exec_command
        cmd(cmd_arg)
    else:                               # Print help when no commands provided
        parser.print_help()
