#!/usr/bin/python
import sys
from sys import argv
import optparse
from os import system
import requests
import subprocess
key = "1e940957819058fe3ec7c59d43c09504b400110db7faa0509"
tkey = "e415520c671c26518df498d8f4736cac"
urbankey = "ub2JDDg9Iumsh1HfdO3a3HQbZi0up1qe8LkjsnWQvyVvQLFn1q"
class dict:
    def __init__(self,key,urbankey,tkey):
        self.key = key
        self.urbankey = urbankey
        self.tkey = tkey
    def getDefinition(self,word):
        definition = requests.get("http://api.wordnik.com/v4/word.json/%s/definitions?api_key=%s" % (word,self.key)).json()
        if len(definition)>=1:
            return definition[0]["text"]
        return definition
    def getHyphenation(self,word):
        hyphenation = requests.get("http://api.wordnik.com/v4/word.json/%s/hyphenation?api_key=%s" % (word,self.key)).json()
        return hyphenation
    def getAudio(self,word):
        url = requests.get("http://api.wordnik.com/v4/word.json/%s/audio?api_key=%s" % (word,self.key)).json()
        if len(url)>=1:
            url = url[0]["fileUrl"]
        else:
            return False,"",""
        return True,url,requests.get(url)
    def getUrban(self,word):
        urb = requests.get("https://mashape-community-urban-dictionary.p.mashape.com/define?term=%s"
        % word, headers={"X-Mashape-Key": self.urbankey}).json()
        if len(urb["list"])>0:
            return urb["list"][0]["definition"]
    def getThesaurus(self,word):
        response = requests.get("http://words.bighugelabs.com/api/2/%s/%s/json"
                            % (self.tkey, word)).json()
        return response


def which(program): #credit to http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python
    import os
    def is_exe(fpath):
        return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

    fpath, fname = os.path.split(program)
    if fpath:
        if is_exe(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            path = path.strip('"')
            exe_file = os.path.join(path, program)
            if is_exe(exe_file):
                return exe_file

    return None
""" Returns the options that the user
defined as well as the actual argument defined"""


def get_args():
    arg = optparse.OptionParser()
    arg.add_option("-a", "--audio", action="store_true", help='audio playback for the the search result', default=False)
    arg.add_option("-t", "--thesaurus", action="store_true", help='show search results using thesaurus', default=False)
    arg.add_option("-u", "--urban", action="store_true", help='show search results using urbandictionary.com', default=False)
    if which("dict") and which("dictd") is not None:
        arg.add_option("-l", "--local", action="store_true", help='show search results using local dict and dictd dictionary', default=False)
    return arg.parse_args(argv)


def check_args_valid(required_args):
    if len(required_args) == 1:
        print("usage: define [options]\
        \n-a, --audio Audio pronounciations\
        \n-t, --thesaurus Thesaurus\
        \n-u, --urban, Search Urban Dictionary instead of Wordnik")
        sys.exit()


def get_wordapi_client():
    return dict(key,urbankey,tkey)


def play_definition(word, client):
    if sys.version_info > (3,):
        ask = input("\nWould you like to hear audio pronounciation? [y/N] ")
    else:
        ask = raw_input("\nWould you like to hear audio pronounciation? [y/N] ")

    if ask.lower().startswith("y"):
        valid,url,obj = client.getAudio(word)
        if valid==False:
            print("Couldn't get Audio")
            return
        # filen = wget.download(url,"/tmp")
        down = obj.content
        filen = url.split("/")[5]
        buff = open("/tmp/%s" % filen, "wb")
        buff.write(down)
        buff.close()
        system("gst-launch-1.0 playbin uri=file:///tmp/%s -q" % filen)
        while True:
            if sys.version_info > (3,):
                ask = input("\nWould you like to hear it again? [y/N] ")
            else:
                ask = raw_input("\nWould you like to hear it again? [y/N] ")
            if ask.lower().startswith("y"):
                system("gst-launch-1.0 -q playbin uri=file:///tmp/%s" % filen)
            else:
                break


def print_urban_dictionary_definition(word,client):
    urb = client.getUrban(word)
    if urb:
        print(word.upper() + ":\n" + client.getUrban(word))
    else:
        print("Couldn't get definition from urbandictionary.com")

def print_wordnik_definition(word, client):
    try:
        cons = []
        for i in client.getHyphenation(word):
            cons.append(i["text"])
        print(word.upper() + " " + "-".join(cons) + ": \n" +
              client.getDefinition(word))
    except TypeError:
        print("Not Found")
        sys.exit()
    except requests.exceptions.ConnectionError:
        if which("dict")!=None:
            fallback = raw_input("There was a connection error, but dict was detected. Would you like to use dict? [y/N] ")
            if fallback.lower().startswith("y"):
                definitions = getLocalDefinitions(word)
                if len(definitions)>=1:
                    print(definitions[0])
            else:
                pass
def getLocalDefinition(word):
    definitions=[]
    output = subprocess.Popen(["dict",word],stdout=subprocess.PIPE)
    output = output.communicate()[0]
    try:
        lines = str(output,encoding="utf-8").split("\n")
    except TypeError: #screw you python3
        lines = output.split("\n")
    for i,v in enumerate(lines):
        if v.startswith("     "):
            if v[5].isdigit():
                endline = None
                for a,b in enumerate(lines[i:]):
                    if b.startswith("        ["):
                        endline = a+i
                        definitions.append(" ".join(lines[i:endline]).replace("        ","")[8:])
                        #print(lines[i:endline])
                        break
    return definitions


def getLocalAudio(word):
    if sys.version_info > (3,):
        ask = input("\nWould you like to hear audio pronounciation? [y/N] ")
    else:
        ask = raw_input("\nWould you like to hear audio pronounciation? [y/N] ")
    if ask.lower().startswith("y"):
        system("espeak %s" % word)
    else:
        pass
    while True:
        if sys.version_info > (3,):
            ask = input("\nWould you like to hear it again? [y/N] ")
        else:
            ask = raw_input("\nWould you like to hear it again? [y/N] ")
        if ask.lower().startswith("y"):
            system("espeak %s" % word)
        else:
            break

def print_thesaurus_response(word,client):
    response = client.getThesaurus(word)
    print("SYNONYMS: ")
    if "noun" in response:
        print("\nNouns:\n%s" % " ".join(response["noun"]["syn"]))
    if "verb" in response:
        print("Verbs:\n%s" % " ".join(response["verb"]["syn"]))


""" Given a list of words, this function will
write their respective definitions on the terminal."""


def print_each_definition(words, client, optional_args):
    audio = optional_args.audio
    thesaurus = optional_args.thesaurus
    urban = optional_args.urban
    local = optional_args.local
    for word in words[1:]:
        if urban:
            print_urban_dictionary_definition(word,client)
        elif local:
            print(word.upper()+":\n"+getLocalDefinition(word)[0])
        else:
            print_wordnik_definition(word, client)
        if thesaurus:
            print_thesaurus_response(word,client)
        if audio and local and which("espeak"):
            getLocalAudio(word)
        elif audio:
            play_definition(word, client)

if __name__ == "__main__":
    (optional_args, required_args) = get_args()
    check_args_valid(required_args)
    client = get_wordapi_client()
    print_each_definition(required_args, client, optional_args)
