#!/usr/bin/env python3

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

##### SPLAT IMPORTS ####################################################################################################
from splat.SPLAT import SPLAT

##### GLOBAL VARIABLES #################################################################################################
my_splat = SPLAT('NULL NULL')
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}
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 taggers."))
    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 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(["which", "java"], 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)
    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():
    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)
        run_command(args[:-1])
        save_splat(args)

if __name__ == "__main__":
    main()
