#!/usr/bin/env python3

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

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

##### GLOBAL VARIABLES #################################################################################################
my_bubble = None
commands = {}

########################################################################################################################
##### 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 commands 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("bubble", "--", "<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("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("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. """
    message = "USAGE:\tsplat <command> <options> <text_source>"
    return message

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

def info_message():
    """ Display copyright information. """
    prog_info = "\n####################################################################"
    prog_info += "\n# SPLAT - Speech Processing & Linguistic Analysis Tool\t\t   #"
    prog_info += "\n# Copyright (C) 2016, Benjamin S. Meyers < ben@splat-library.org > #"
    prog_info += "\n# \t\t\t\t\t\t\t\t   #"
    prog_info += "\n# Developed by Benjamin S. Meyers under the guidance of:\t   #"
    prog_info += "\n#\tEmily Prud'hommeaux\tCissi O. Alm\t\t\t   #"
    prog_info += "\n# \t\t\t\t\t\t\t\t   #"
    prog_info += "\n# For documentation, visit: http://splat-library.org\t\t   #"
    prog_info += "\n####################################################################\n"
    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\tpython3 -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")

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

    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_bubble(args):
    global my_bubble
    if os.path.exists(args[-1] + ".splat"):
        temp_str = ""
        with open(args[-1] + ".splat", 'r') as f:
            temp_str = f.read().replace('\n', '')
        my_bubble = jsonpickle.decode(temp_str)
    else:
        my_bubble = SPLAT(args[-1])
        new_bubble = jsonpickle.encode(my_bubble)
        with open(args[-1] + ".splat", 'w') as f:
            f.write(new_bubble)

def save_bubble(args):
    global my_bubble
    temp_bubble = jsonpickle.encode(my_bubble)
    with open(args[-1] + ".splat", 'w') as f:
        f.write(temp_bubble)

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

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_bubble(args)
        setup_commands()
        run_command(args[:-1])
        save_bubble(args)

if __name__ == "__main__":
    main()
