#!/usr/bin/env python3

##### PYTHON IMPORTS ###################################################################################################
import os, subprocess, sys, json

##### SPLAT IMPORTS ####################################################################################################
try:
    from splat.SPLAT import SPLAT
except ImportError:
    sys.path.append(".")
    #this_dir = os.path.dirname(os.path.abspath(__file__))
    from .SPLAT import SPLAT

##### GLOBAL VARIABLES #################################################################################################
my_splat = SPLAT('NULL NULL NULL')
commands = {}
prog_info = "\n####################################################################" \
            "\n# SPLAT - Speech Processing & Linguistic Analysis Tool\t\t   #" \
            "\n# Copyright (C) 2016, Benjamin S. Meyers < ben@splat-library.org > #" \
            "\n# \t\t\t\t\t\t\t\t   #" \
            "\n# Developed by Benjamin S. Meyers under the guidance of:\t   #" \
            "\n#\tEmily Prud'hommeaux\tCissi O. Alm\t\t\t   #" \
            "\n# \t\t\t\t\t\t\t\t   #" \
            "\n# For documentation, visit: http://splat-library.org\t\t   #" \
            "\n####################################################################\n"

########################################################################################################################
##### INFORMATION ######################################################################################################
### @PROJECT_NAME:		SPLAT: Speech Processing and Linguistic Analysis Tool										 ###
### @VERSION_NUMBER:																								 ###
### @PROJECT_SITE:		github.com/meyersbs/SPLAT																     ###
### @AUTHOR_NAME:		Benjamin S. Meyers																			 ###
### @CONTACT_EMAIL:		ben@splat-library.org																		 ###
### @LICENSE_TYPE:		MIT																							 ###
########################################################################################################################
########################################################################################################################

#TODO: TextGrid Support
#TODO: String-Based Yngve
#TODO: String-Based Frazier
#TODO: ProsodyLab Aligner Support?
#TODO: Config File
#TODO: Moving Window

def command_message():
    """ Display all available command-line arguments and their descriptions. """
    template = "{0:16}{1:8}{2:16}{3:128}"
    print(template.format("COMMAND", "ARG1", "ARG2", "DESCRIPTION"))
    print(template.format("adps", "--", "<input_file>", "Display average disfluencies per sentence."))
    print(template.format("adpu", "--", "<input_file>", "Display average disfluencies per utterance."))
    print(template.format("asps", "--", "<input_file>", "Display average syllables per sentence."))
    print(template.format("aspu", "--", "<input_file>", "Display average syllables per utterance."))
    print(template.format("als", "--", "<input_file>", "Display average sentence length."))
    print(template.format("alu", "--", "<input_file>", "Display average utterance length."))
    print(template.format("bigrams", "--", "<input_file>", "Display all bigrams."))
    print(template.format("splat", "--", "<input_file>", "Display the raw SPLAT."))
    print(template.format("cdensity", "--", "<input_file>", "Display content density."))
    print(template.format("cfr", "--", "<input_file>", "Display content-function ratio."))
    print(template.format("content", "--", "<input_file>", "Display all content words."))
    print(template.format("disfluencies", "--", "<input_file>", "Display all disfluency counts."))
    print(template.format("dps", "--", "<input_file>", "Display disfluencies per sentence."))
    print(template.format("dpu", "--", "<input_file>", "Display disfluencies per utterance."))
    print(template.format("drawtrees", "--", "<input_file>", "Draw syntactic parsers trees."))
    print(template.format("flesch", "--", "<input_file>", "Display Flesch Readability Score."))
    print(template.format("frazier", "--", "<input_file>", "Display frazier score."))
    print(template.format("function", "--", "<input_file>", "Display all function words."))
    print(template.format("idensity", "--", "<input_file>", "Display idea density."))
    print(template.format("json", "--", "<input_file>", "Display JSON Object."))
    print(template.format("kincaid", "--", "<input_file>", "Display Flesch-Kincaid Grade Level."))
    print(template.format("leastfreq", "<x>", "<input_file>", "Display the <x> least frequent words."))
    print(template.format("lwords", "--", "<input_file>", "Display the longest words."))
    print(template.format("maxdepth", "--", "<input_file>", "Display maxdepth of trees."))
    print(template.format("maxcdensity", "--", "<input_file>", "Display max content density."))
    print(template.format("maxidensity", "--", "<input_file>", "Display max idea density."))
    print(template.format("mincdensity", "--", "<input_file>", "Display min content density."))
    print(template.format("mincdensity", "--", "<input_file>", "Display min idea density."))
    print(template.format("mostfreq", "<x>", "<input_file>", "Display the <x> most frequent words."))
    print(template.format("ngrams", "<n>", "<input_file>", "Display all <n>-grams."))
    print(template.format("plotfreq", "--", "<input_file>", "Plot the <x> most frequent words."))
    print(template.format("pos", "--", "<input_file>", "Display tokens with POS tags."))
    print(template.format("poscounts", "--", "<input_file>", "Display counts for each POS tag."))
    print(template.format("pronouns", "--", "<input_file>", "Display counts for each Pronoun."))
    print(template.format("sents", "--", "<input_file>", "Display sentences."))
    print(template.format("sentcount", "--", "<input_file>", "Display number of sentences."))
    print(template.format("sfrazier", "--", "<input_file>", "Display string-based frazier score."))
    print(template.format("swords", "--", "<input_file>", "Display the shortest words."))
    print(template.format("syllables", "--", "<input_file>", "Display number of syllables."))
    print(template.format("syngve", "--", "<input_file>", "Display string-based yngve score."))
    print(template.format("tokens", "--", "<input_file>", "Display all tokens."))
    print(template.format("trees", "--", "<input_file>", "Display all parsers trees."))
    print(template.format("trigrams", "--", "<input_file>", "Display all trigrams."))
    print(template.format("ttr", "--", "<input_file>", "Display type-token ratio."))
    print(template.format("types", "--", "<input_file>", "Display all types."))
    print(template.format("ucontent", "--", "<input_file>", "Display all unique content words."))
    print(template.format("ufunction", "--", "<input_file>", "Display all unique function words."))
    print(template.format("unigrams", "--", "<input_file>", "Display all unigrams."))
    print(template.format("uttcount", "--", "<input_file>", "Display number of utterances."))
    print(template.format("utts", "--", "<input_file>", "Display utterances."))
    print(template.format("uwc", "--", "<input_file>", "Display unique wordcount."))
    print(template.format("wc", "--", "<input_file>", "Display wordcount."))
    print(template.format("wps", "--", "<input_file>", "Display words per sentence counts."))
    print(template.format("wpu", "--", "<input_file>", "Display words per utterance counts."))
    print(template.format("yngve", "--", "<input_file>", "Display yngve score."))

def setup_commands():
    global commands
    commands = {"wc": my_splat.wordcount, "uwc": my_splat.unique_wordcount, "tokens": my_splat.tokens,
                "types": my_splat.types, "sents": my_splat.sents, "sentcount": my_splat.sentcount,
                "ttr": my_splat.type_token_ratio, "ngrams": my_splat.ngrams, "pos": my_splat.pos,
                "alu": my_splat.average_utterance_length, "cfr": my_splat.content_function_ratio,
                "uttcount": my_splat.uttcount, "unigrams": my_splat.unigrams, "bigrams": my_splat.bigrams,
                "trigrams": my_splat.trigrams, "content": my_splat.content_words, "function": my_splat.function_words,
                "ucontent": my_splat.unique_content_words, "asps": my_splat.average_sps,
                "ufunction": my_splat.unique_function_words, "trees": my_splat.treestrings,
                "drawtrees": my_splat.drawtrees, "wpu": my_splat.words_per_utterance,
                "wps": my_splat.words_per_sentence, "utts": my_splat.utts, "cdensity": my_splat.content_density,
                "idensity": my_splat.idea_density, "aspu": my_splat.average_spu,
                "yngve": my_splat.tree_based_yngve_score, "frazier": my_splat.tree_based_frazier_score,
                "json": my_splat.dumps, "poscounts": my_splat.pos_counts, "maxdepth": my_splat.max_depth,
                "mostfreq": my_splat.get_most_freq, "leastfreq": my_splat.get_least_freq,
                "plotfreq": my_splat.plot_freq, "disfluencies": my_splat.disfluencies,
                "dpu": my_splat.disfluencies_per_utterance, "dps": my_splat.disfluencies_per_sentence,
                "splat": my_splat.splat, "als": my_splat.average_sentence_length,
                "syngve": my_splat.string_based_yngve_score, "sfrazier": my_splat.string_based_frazier_score,
                "lwords": my_splat.longest_words, "swords": my_splat.shortest_words, "syllables": my_splat.syllables,
                "flesch": my_splat.flesch_readability, "kincaid": my_splat.kincaid_grade_level,
                "adpu": my_splat.average_dpu, "adps": my_splat.average_dps, "maxcdensity": my_splat.max_content_density,
                "mincdensity": my_splat.min_content_density, "maxidensity": my_splat.max_idea_density,
                "minidensity": my_splat.min_idea_density, "pronouns": my_splat.pronouns}

def usage_message():
    """ Display usage message. """
    return "USAGE:\tsplat <command> <options> <text_source>"

def help_message():
    """ Display help message. """
    return "USAGE:\tsplat <command> <options> <text_source>\n\tsplat --commands\tList available commands.\n\tsplat " \
           "--info\t\tDisplay licensing information.\n"

def info_message():
    """ Display copyright information. """
    global prog_info
    return prog_info

def check_dependencies():
    """
    SPLAT relies on the modules matplotlib and nltk for certain functionality.
    It also relies on Java being installed in order for the Berkeley Parser to be used.
    """
    try:
        import nltk
    except ImportError:
        print("Oops! It looks like NLTK was not installed. Let's fix that.")
        print("Installing NLTK...")
        status = subprocess.call(["pip3", "install", "nltk"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if status == 0:
            print("NLTK was successfully installed!")
        else:
            print("Hmm... I couldn't install NLTK for you. You probably don't have root privileges. I suggest running"
                  "this command:\n\tsudo pip3 install nltk")

    try:
        from nltk.corpus import stopwords
        from nltk.corpus import names
        from nltk.tokenize import punkt
        from nltk import pos_tag
    except ImportError:
        print("Oops! It looks like some essential NLTK was not downloaded. Let's fix that.")
        print("Downloading NLTK data...")
        status = subprocess.call(
            ["python3", "-m", "nltk.downloader", "stopwords", "names", "punkt", "averaged_perceptron_tagger"],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if status == 0:
            print("Essential NLTK data was successfully downloaded!")
        else:
            print("Hmm... I couldn't download the essential NLTK data for you. I suggest running this command:\n\t"
                  "python3 -m nltk.downloader stopwords names punkt averaged_perceptron_tagger")

    try:
        import matplotlib
    except ImportError:
        print("Oops! It looks like matplotlib was not installed. Let's fix that.")
        print("Installing matplotlib...")
        status = subprocess.call(["pip3", "install", "matplotlib"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if status == 0:
            print("matplotlib was successfully installed!")
        else:
            print("Hmm... I couldn't install matplotlib for you. You probably don't have root privileges. I suggest"
                  "running this command:\n\tsudo pip3 install matplotlib")

    java_status = subprocess.call(["java", "-version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if java_status != 0:
        print("Java is not installed on your system. Java needs to be installed in order for me to do any"
              "part-of-speech tagging.\n\nPlease install java and try again.")


def run_command(args):
    command = args[1]
    if command not in commands.keys():
        sys.exit("WARNING: Invalid command. Try '--help' for details.")
    if len(args) == 2: # splat <command>
        print(commands[command]())
    elif len(args) == 3: # splat <command> <option>
        try:
            print(commands[command](int(args[2])))
        except:
            print("WARNING: Could not run " + str(command) + " with missing arguments.")

def load_splat(args):
    global my_splat
    if os.path.exists(args[-1] + ".splat"):
        with open(args[-1] + ".splat", 'r') as f:
            my_splat.load(f)
    elif os.path.exists(args[-1][0:20] + ".splat"):
        with open(args[-1][0:20] + ".splat", 'r') as f:
            my_splat.load(f)
    else:
        my_splat = SPLAT(args[-1])
        save_splat(args)

def save_splat(args):
    global my_splat
    with open(args[-1] + ".splat", 'w') as f:
        my_splat.dump(f)

def main():
    global my_splat
    args = sys.argv
    if len(args) < 2:
        sys.exit("WARNING: Invalid input. Try '--help' for more details.")
    elif len(args) == 2:
        check_dependencies()
        if args[1] == "--help":
            print(help_message())
        elif args[1] == "--info":
            print(info_message())
        elif args[1] == "--usage":
            print(usage_message())
        elif args[1] == "--commands":
            command_message()
    else:
        check_dependencies()
        load_splat(args)
        setup_commands()
        run_command(args[:-1])
        save_splat(args)

if __name__ == "__main__":
    main()
