# Physical Computing Final Project - Prof. John Gallaugher
# Daniel Flores
# Marvel's Black Panther Equipment
import board, time, neopixel, digitalio, busio, pwmio
import adafruit_fingerprint
from adafruit_debouncer import Debouncer
from digitalio import DigitalInOut, Direction
from audiocore import WaveFile
from adafruit_led_animation.animation.SparklePulse import SparklePulse
from adafruit_motor import servo

try:
    from audioio import AudioOut
except ImportError:
    try:
        from audiopwmio import PWMAudioOut as AudioOut
    except ImportError:
        print("This board does not suport AudioOut")
        pass

audio = AudioOut(board.D5)
path = "panther/"

pwm = pwmio.PWMOut(board.D9, frequency = 50)
servo_1 = servo.Servo(pwm, max_pulse = 2370)


button_1 = digitalio.DigitalInOut(board.D2)
button_1.switch_to_input(pull=digitalio.Pull.UP)
button1 = Debouncer(button_1)

button_2 = digitalio.DigitalInOut(board.D3)
button_2.switch_to_input(pull=digitalio.Pull.UP)
button2 = Debouncer(button_2)

strip_pin = board.D7
strip_num_of_lights = 30
strip = neopixel.NeoPixel(strip_pin, strip_num_of_lights, brightness = 0.5, auto_write = True)

BLUE = (0,0,255)
BLACK = (0,0,0)


sparkle_pulse_strip = SparklePulse(strip, speed = 0.05, period = 5, color = BLUE)

led = DigitalInOut(board.D13)
led.direction = Direction.OUTPUT

uart = busio.UART(board.TX, board.RX, baudrate=57600)
finger = adafruit_fingerprint.Adafruit_Fingerprint(uart)


def get_fingerprint():
    """Get a finger print image, template it, and see if it matches!"""
    print("Waiting for image...")
    while finger.get_image() != adafruit_fingerprint.OK:
        pass
    print("Templating...")
    if finger.image_2_tz(1) != adafruit_fingerprint.OK:
        return False
    print("Searching...")
    if finger.finger_search() != adafruit_fingerprint.OK:
        return False
    return True

def get_fingerprint_detail():
    """Get a finger print image, template it, and see if it matches!
    This time, print out each error instead of just returning on failure"""
    print("Getting image...", end="")
    i = finger.get_image()
    if i == adafruit_fingerprint.OK:
        print("Image taken")
    else:
        if i == adafruit_fingerprint.NOFINGER:
            print("No finger detected")
        elif i == adafruit_fingerprint.IMAGEFAIL:
            print("Imaging error")
        else:
            print("Other error")
        return False
    print("Templating...", end="")
    i = finger.image_2_tz(1)
    if i == adafruit_fingerprint.OK:
        print("Templated")
    else:
        if i == adafruit_fingerprint.IMAGEMESS:
            print("Image too messy")
        elif i == adafruit_fingerprint.FEATUREFAIL:
            print("Could not identify features")
        elif i == adafruit_fingerprint.INVALIDIMAGE:
            print("Image invalid")
        else:
            print("Other error")
        return False

    print("Searching...", end="")
    i = finger.finger_fast_search()
    # pylint: disable=no-else-return
    # This block needs to be refactored when it can be tested.
    if i == adafruit_fingerprint.OK:
        print("Found fingerprint!")
        return True
    else:
        if i == adafruit_fingerprint.NOTFOUND:
            print("No match found")
        else:
            print("Other error")
        return False

def enroll_finger(location):
    """Take a 2 finger images and template it, then store in 'location'"""
    for fingerimg in range(1, 3):
        if fingerimg == 1:
            print("Place finger on sensor...", end="")
        else:
            print("Place same finger again...", end="")

        while True:
            i = finger.get_image()
            if i == adafruit_fingerprint.OK:
                print("Image taken")
                break
            if i == adafruit_fingerprint.NOFINGER:
                print(".", end="")
            elif i == adafruit_fingerprint.IMAGEFAIL:
                print("Imaging error")
                return False
            else:
                print("Other error")
                return False

        print("Templating...", end="")
        i = finger.image_2_tz(fingerimg)
        if i == adafruit_fingerprint.OK:
            print("Templated")
        else:
            if i == adafruit_fingerprint.IMAGEMESS:
                print("Image too messy")
            elif i == adafruit_fingerprint.FEATUREFAIL:
                print("Could not identify features")
            elif i == adafruit_fingerprint.INVALIDIMAGE:
                print("Image invalid")
            else:
                print("Other error")
            return False

        if fingerimg == 1:
            print("Remove finger")
            time.sleep(1)
            while i != adafruit_fingerprint.NOFINGER:
                i = finger.get_image()

    print("Creating model...", end="")
    i = finger.create_model()
    if i == adafruit_fingerprint.OK:
        print("Created")
    else:
        if i == adafruit_fingerprint.ENROLLMISMATCH:
            print("Prints did not match")
        else:
            print("Other error")
        return False

    print("Storing model #%d..." % location, end="")
    i = finger.store_model(location)
    if i == adafruit_fingerprint.OK:
        print("Stored")
    else:
        if i == adafruit_fingerprint.BADLOCATION:
            print("Bad storage location")
        elif i == adafruit_fingerprint.FLASHERR:
            print("Flash storage error")
        else:
            print("Other error")
        return False

    return True

def get_num():
    """Use input() to get a valid number from 1 to 127. Retry till success!"""
    i = 0
    while (i > 127) or (i < 1):
        try:
            i = int(input("Enter ID # from 1-127: "))
        except ValueError:
            pass
    return i

def play_sound(filename):
    with open(path + filename, "rb") as wave_file:
        wave = WaveFile(wave_file)
        audio.play(wave)
        while audio.playing:
            sparkle_pulse_strip.animate()

servo_1.angle =  0
while True:
    button1.update()
    button2.update()

    if finger.read_templates() != adafruit_fingerprint.OK:
        raise RuntimeError("Failed to read templates!!")

    if button1.fell:
        if get_fingerprint():
            print("button 1 is pressed")
            play_sound("latchopening.wav")
            for i in range(0, 181, 1):
                servo_1.angle = i
            time.sleep(0.5)
            play_sound("wakandaforever.wav")
            servo_1.angle = 0
    if button2.fell:
        if get_fingerprint():
            print("button 2 is pressed")
            play_sound("latchopening.wav")
            for i in range(180, -1, -1):
                servo_1.angle = i
            time.sleep(0.5)
            play_sound("drums.wav")
            servo_1.angle = 0
