import board, pwmio, time, digitalio
import re
from adafruit_motor import servo
import subprocess
import tempfile
import os
from pydub import AudioSegment
from pydub.playback import play
import concurrent.futures
import sys

UP = 0
MID = 45
SEMI_DOWN = 95
DOWN = 115
OPEN = True 
CLOSED = False
THUMB_THROTTLE = .5
THUMB_TIME = .40
UPRIGHT = False
SIDEWAYS = True

LETTER_MAP = {
    "A": [DOWN, DOWN, DOWN, DOWN, OPEN, UPRIGHT],
    "B": [UP, UP, UP, UP, CLOSED, UPRIGHT],
    "C": [MID, MID, MID, MID, CLOSED, UPRIGHT],
    "D": [DOWN, DOWN, DOWN, UP, CLOSED, UPRIGHT],
    "E": [SEMI_DOWN, SEMI_DOWN, SEMI_DOWN, SEMI_DOWN, CLOSED, UPRIGHT],
    "F": [UP, UP, UP, DOWN, CLOSED, UPRIGHT],
    "G": [DOWN, DOWN, DOWN, MID, CLOSED, SIDEWAYS],
    "H": [DOWN, DOWN, MID, MID, CLOSED, SIDEWAYS],
    "I": [UP, DOWN, DOWN, DOWN, CLOSED, UPRIGHT],
    "J": [UP, DOWN, DOWN, DOWN, CLOSED, SIDEWAYS],
    "K": [DOWN, DOWN, UP, UP, CLOSED, UPRIGHT],
    "L": [DOWN, DOWN, DOWN, UP, OPEN, UPRIGHT],
    "M": [DOWN, SEMI_DOWN, SEMI_DOWN, SEMI_DOWN, OPEN, UPRIGHT],
    "N": [DOWN, DOWN, SEMI_DOWN, SEMI_DOWN, OPEN, UPRIGHT],
    "O": [MID, MID, MID, MID, CLOSED, UPRIGHT],
    "P": [DOWN, DOWN, SEMI_DOWN, MID, CLOSED, SIDEWAYS],
    "Q": [DOWN, DOWN, DOWN, MID, CLOSED, SIDEWAYS],
    "R": [DOWN, SEMI_DOWN, UP, UP, CLOSED, UPRIGHT],
    "S": [DOWN, DOWN, DOWN, DOWN, CLOSED, UPRIGHT],
    "T": [DOWN, DOWN, SEMI_DOWN, SEMI_DOWN, CLOSED, UPRIGHT],
    "U": [DOWN, DOWN, UP, UP, CLOSED, UPRIGHT],
    "V": [DOWN, DOWN, UP, UP, CLOSED, UPRIGHT],
    "W": [DOWN, DOWN, SEMI_DOWN, MID, CLOSED, UPRIGHT],
    "X": [DOWN, UP, UP, UP, CLOSED, UPRIGHT],
    "Y": [UP, DOWN, DOWN, DOWN, OPEN, UPRIGHT],
    "Z": [DOWN, DOWN, DOWN, UP, CLOSED, UPRIGHT],
}

#Thumb will need to be 180 to 90.

# With Blinka we use board.D2 rather than board.GP2
pwm1 = pwmio.PWMOut(board.D2, frequency=50)
pwm2 = pwmio.PWMOut(board.D3, frequency=50)
pwm3 = pwmio.PWMOut(board.D4, frequency=50)
pwm4 = pwmio.PWMOut(board.D17, frequency=50)
pwm5 = pwmio.PWMOut(board.D27, frequency=50)

pinky = servo.Servo(pwm1, min_pulse=500, max_pulse = 2270)
ring = servo.Servo(pwm2, min_pulse=500, max_pulse = 2290)
middle = servo.Servo(pwm3, min_pulse=500, max_pulse = 2310)
pointer = servo.Servo(pwm4, min_pulse=500, max_pulse = 2270)
thumb = servo.ContinuousServo(pwm5)
thumb_open = True

led = digitalio.DigitalInOut(board.D22)
led.direction = digitalio.Direction.OUTPUT

fingers = [pinky, ring, middle, pointer]

def synthesize_speech(text, voice_model_path, output_file="output.wav"):
    try:
        with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as temp_input_file:
            temp_input_file.write(text)
            temp_input_file_path = temp_input_file.name
        command = [
            "piper",
            "-m", voice_model_path,
            "-f", output_file,  # Use -f for the output file
        ]
        result = subprocess.run(command, input=text, text=True, capture_output=True)
        if result.returncode == 0:
            print(f"Audio saved to {output_file}")
            return output_file
        else:
            print(f"Piper Error: {result.stderr}")
            return None
    finally:
        if os.path.exists(temp_input_file_path):
            os.remove(temp_input_file_path)

def play_audio(audio_file):
    try:
        # Load and play the audio using pydub
        audio = AudioSegment.from_file(audio_file)
        play(audio)
    except Exception as e:
        print(f"Error playing audio: {e}")

def spell_word(input):
    global thumb_open
    letters = [char.upper() for char in re.sub(r'[^a-zA-Z]', '', input)]
    for letter in letters:
        audio_file = "./alphabet/" + letter + ".wav"
        positions = LETTER_MAP[letter]
        for i in range(4):
            fingers[i].angle = positions[i]
        if positions[4] is not thumb_open:
            thumb.throttle = (0 - THUMB_THROTTLE) if thumb_open else THUMB_THROTTLE
            time.sleep(.5)
            thumb.throttle = 0
            time.sleep(1)
            thumb_open = not thumb_open
        led.value = positions[5]
        print(letter)
        play_audio(audio_file)
        time.sleep(1.5)
    
def reset_hand():
    global thumb_open
    for finger in fingers:
        finger.angle = UP
    if thumb_open is False:
        thumb.throttle = 1
        time.sleep(THUMB_TIME)
        thumb.throttle = 0
        time.sleep(1)
        thumb_open = True
    led.value = False

def main():
    voice_model_path = "/home/sanforlu/Documents/voice_models/en_US-ryan-medium.onnx"
    while True:
        os.system("clear")
        print("========================================================")
        print("Enter the word you want to spell in sign-language: ")
        user_text = input("> ")
        text_for_speech = "That is how you spell: " + user_text + " in sign-language"
        output_audio_path = "output.wav"

        with concurrent.futures.ThreadPoolExecutor() as executor:
            future = executor.submit(synthesize_speech, text_for_speech, voice_model_path, output_audio_path)
            spell_word(user_text)  # Replace with your actual tasks
            audio_file = future.result()
            reset_hand()
            play_audio(audio_file)

if __name__ == "__main__":
    main()


