# Imports
import python_weather
from playsound import playsound
import asyncio
import datetime
import time
import sys
from subprocess import Popen
import pyttsx3 as tts
import pywhatkit
import speech_recognition as sr
from neuralintents import GenericAssistant

# ================== End of Imports ====================
# setup and initialization
recognizer = sr.Recognizer()

todo_list = ['Go Shopping', 'Clean Room', 'Take out the trash', 'Write program']


# ======================= End of Initializations ====================
# functions
# this function to clean up repetitive typing of Jarvis.say and Jarvis.runAndWait()


def talk(text):
    engine = tts.init()
    engine.setProperty('rate', 150)
    engine.say(text)
    engine.runAndWait()


# opening programs' section goes here.
def open_chrome():
    global recognizer, audio, message

    done = False

    while not done:
        try:

            with sr.Microphone() as mic:

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)
                #
                program = recognizer.recognize_google(audio)
                program = program.lower()
                Popen([r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"])
                talk("I opened Chrome for you Kelly")
                print(program)
                #
                done = True
        #
        except sr.UnknownValueError:
            recognizer = sr.Recognizer()
            talk("I did not understand you! Please try again!")
        #


def open_wow():
    global recognizer, audio, message

    done = False
    #
    while not done:
        try:

            with sr.Microphone() as mic:

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)
                #
                program = recognizer.recognize_google(audio)
                program = program.lower()
                Popen([r"C:\Program Files (x86)\World of Warcraft\World of Warcraft Launcher.exe"])
                talk("I opened wow for you Kelly")
                print(program)
                #
                done = True
        #
        except sr.UnknownValueError:
            recognizer = sr.Recognizer()
            talk("I did not understand you! Please try again!")
        #


def open_ldplayer():
    global recognizer, audio, message

    done = False

    while not done:
        try:

            with sr.Microphone() as mic:

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)

                program = recognizer.recognize_google(audio)
                program = program.lower()
                Popen([r"C:\LDPlayer\LDPlayer4.0\dnplayer.exe"])
                talk("I opened LD Player for you Kelly")
                print(program)

                done = True

        except sr.UnknownValueError:
            recognizer = sr.Recognizer()
            talk("I did not understand you! Please try again!")


async def getweather():
    # declare the client. format defaults to the metric system (celcius, km/h, etc.)
    client = python_weather.Client(format=python_weather.IMPERIAL)
    # fetch a weather forecast from a city
    weather = await client.find("brinkley arkansas")

    # returns the current day's forecast temperature (int)
    talk(weather.current.temperature)
    print(weather.current.temperature)

    # get the weather forecast for a few days
    for forecast in weather.forecasts:
        talk(str(forecast.date))
        talk(str(forecast.sky_text))
        talk(str(forecast.temperature))
        print(str(forecast.date), forecast.sky_text, forecast.temperature)

    # close the wrapper once done
    await client.close()


def open_weather():
    global recognizer, audio, message

    done = False

    while not done:
        try:

            with sr.Microphone() as mic:

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)

                location = recognizer.recognize_google(audio)
                location = location.lower()
                print(location)

                getweather()

                loop = asyncio.get_event_loop()
                loop.run_until_complete(getweather())

                done = True

        except sr.UnknownValueError:
            recognizer = sr.Recognizer()
            talk("I did not understand you! Please try again!")


#
def play_song():
    global recognizer, audio, message

    talk("What do you want to play?")

    done = False

    while not done:
        try:

            with sr.Microphone() as mic:

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)

                filename = recognizer.recognize_google(audio)
                filename = filename.lower()

                pywhatkit.playonyt(filename)
                #
                talk("I opened {filename} for you Kelly")
                #
                done = True

        except sr.UnknownValueError:
            recognizer = sr.Recognizer()
            talk("I did not understand you! Please try again!")


def create_note():
    global recognizer, audio, message
    print(message)

    talk("What do you want to write on your note?")

    done = False

    while not done:
        try:

            with sr.Microphone() as mic:

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)

                note = recognizer.recognize_google(audio)
                note = note.lower()
                print(note)

                talk("Choose a filename!")

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)

                filename = recognizer.recognize_google(audio)
                filename = filename.lower()
                print(filename)

            with open(f"{filename}.txt", 'w') as f:
                f.write(note)
                done = True
                talk("I successfully created the note {filename}")

        except sr.UnknownValueError:
            recognizer = sr.Recognizer()
            talk("I did not understand you! Please try again!")


def add_todo():
    global recognizer, audio, message
    talk("What to do do you want to add?")
    print(message)

    done = False

    while not done:
        try:

            with sr.Microphone() as mic:

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)

                item = recognizer.recognize_google(audio)
                item = item.lower()
                print(item)

                todo_list.append(item)
                done = True

                talk("I added {item} to the to do list!")

        except sr.UnknownValueError:
            recognizer = sr.Recognizer()
            talk("I did not understand you! Please try again!")


def show_todos():
    print(message)
    talk("The items on your to do list are the following")
    for item in todo_list:
        talk(item)
        print(item)


def today_time():
    print(message)
    time_now = datetime.datetime.now().strftime('%I %M %p')
    talk(time_now)
    print(time_now)


def today_day():
    print(message)
    day = datetime.datetime.now().strftime('%A')
    talk(day)
    print(day)


def today_date():
    print(message)
    date = datetime.datetime.now().strftime('%m/%d/%Y')
    talk(date)
    print(date)


def set_timer():
    global recognizer, audio, message
    talk("How long of a timer do you want to set?")
    done = False

    while not done:
        try:

            with sr.Microphone() as mic:

                recognizer.adjust_for_ambient_noise(mic, duration=0.2)
                audio = recognizer.listen(mic)

                timer_length = recognizer.recognize_google(audio)
                timer_length = timer_length.lower()

                if 'hours' in timer_length:
                    time_value = float(timer_length.rstrip('hours'))
                    time_value = time_value * 60 * 60
                    print(time_value)
                    print(type(time_value))

                elif 'hour' in timer_length:
                    time_value = float(timer_length.rstrip('hour'))
                    time_value = time_value * 60 * 60
                    print(time_value)
                    print(type(time_value))

                elif 'minutes' in timer_length:
                    time_value = float(timer_length.rstrip('minutes'))
                    time_value = time_value * 60
                    print(time_value)
                    print(type(time_value))

                elif 'seconds' in timer_length:
                    time_value = float(timer_length.rstrip('seconds'))
                    print(time_value)
                    print(type(time_value))
                else:
                    talk("When shall I start the timer?")
                    while time_value > 0:
                        timer = datetime.timedelta(seconds=time_value)
                        print(timer, end="\r")
                        time.sleep(1)
                        time_value -= 1

                    pass
                    done = True

                    playsound(r"C:\Users\Kelly Mabry\Pythoncode\jarvis\ZT_tone_1.wav")
                    talk("the timer is done, Kelly")


        except sr.UnknownValueError:
            recognizer = sr.Recognizer()
            talk("I did not understand you! Please try again!")


def hello():
    print(message)
    talk("Hello Kelly, What can I do for you?")


def thank_you():
    talk("you are welcome Kelly, its what we do..")


def leave_program():
    print(message)
    # assistant.save_model()
    talk("goodbye Kelly")
    sys.exit(0)


# ======================== End of functions =========================
# mappings go here and are also needed in intents.json
mappings = {
    "greeting": hello,
    "create_note": create_note,
    "add_todo": add_todo,
    "show_todos": show_todos,
    "time": today_time,
    "day": today_day,
    "date": today_date,
    "play_a_song": play_song,
    "thank_you": thank_you,
    "open_wow": open_wow,
    "open_chrome": open_chrome,
    "open_weather": open_weather,
    "set_timer": set_timer,
    "open_ldplayer": open_ldplayer,
    "goodbye": leave_program
}
# End of mappings, training begins here
#
assistant = GenericAssistant('intents.json', intent_methods=mappings)
assistant.train_model()

while True:

    try:

        with sr.Microphone() as mic:

            recognizer.adjust_for_ambient_noise(mic, duration=0.2)
            audio = recognizer.listen(mic)
            message = recognizer.recognize_google(audio)
            message = message.lower()
            assistant.request(message)
    except sr.UnknownValueError:
        recognizer = sr.Recognizer()
