#!/usr/bin/env python3

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

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

##### GLOBAL VARIABLES #################################################################################################
my_splat = SPLAT('NULL NULL')
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("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("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_splat(args):
    global my_splat
    if os.path.exists(args[-1] + ".splat"):
        with open(args[-1] + ".splat", 'r') as f:
            #my_splat = jsonpickle.decode(f.read().replace('\n', ''))
            #my_splat = json.load(f)
            my_splat.load(f)
            print(type(my_splat))
    else:
        my_splat = SPLAT(args[-1])
        save_splat(args)

def save_splat(args):
    global my_splat
    #temp_splat = jsonpickle.encode(my_splat)
    with open(args[-1] + ".splat", 'w') as f:
        my_splat.dump(f)
        #json.dump(my_splat, f, default=jdefault)
        #f.write(temp_splat)

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,
                "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,
                "yngve":my_splat.tree_based_yngve_score, "frazier":my_splat.tree_based_frazier_score,
                "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, "dpu":my_splat.disfluencies_per_utterance,
                "dps":my_splat.disfluencies_per_sentence, "disfluencies":my_splat.disfluencies,
                "als":my_splat.average_sentence_length, "syngve":my_splat.string_based_yngve_score,
                "sfrazier":my_splat.string_based_frazier_score, "splat":my_splat.splat,
                "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, "aspu":my_splat.average_spu,
                "asps":my_splat.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_splat(args)
        setup_commands()
        run_command(args[:-1])
        save_splat(args)

if __name__ == "__main__":
    main()
