import board
import re
import simpleio
import time

PIEZO_PIN = board.GP22

MORSE_PITCH = 700
dot = 0.050   # = 60 / (50 * WPM)
dash = 3*dot
gap = dot
lspace = 3*dot
wspace = 7*dot

MORSE_CHARS = {
    "A":(dot, dash),
    "B":(dash, dot, dot, dot),
    "C":(dash, dot, dash, dot),
    "D":(dash, dot, dot),
    "E":(dot,),
    "F":(dot, dot, dash, dot),
    "G":(dash, dash, dot),
    "H":(dot, dot, dot, dot),
    "I":(dot, dot),
    "J":(dot, dash, dash, dash),
    "K":(dash, dot, dash),
    "L":(dot, dash, dot, dot),
    "M":(dash, dash),
    "N":(dash, dot),
    "O":(dash, dash, dash),
    "P":(dot, dash, dash, dot),
    "Q":(dash, dash, dot, dash),
    "R":(dot, dash, dot),
    "S":(dot, dot, dot),
    "T":(dash,),
    "U":(dot, dot, dash),
    "V":(dot, dot, dot, dash),
    "W":(dot, dash, dash),
    "X":(dash, dot, dot, dash),
    "Y":(dash, dot, dash, dash),
    "Z":(dash, dash, dot, dot),
    
    "0":(dash, dash, dash, dash, dash),
    "1":(dot, dash, dash, dash, dash),
    "2":(dot, dot, dash, dash, dash),
    "3":(dot, dot, dot, dash, dash),
    "4":(dot, dot, dot, dot, dash),
    "5":(dot, dot, dot, dot, dot),
    "6":(dash, dot, dot, dot, dot),
    "7":(dash, dash, dot, dot, dot),
    "8":(dash, dash, dash, dot, dot),
    "9":(dash, dash, dash, dash, dot),
    
    # https://en.wikipedia.org/wiki/Prosigns_for_Morse_code
    "?":(dot, dot, dash, dash, dot, dot), # ? - SAY AGAIN or indicate question/request
    "AR":(dot, dash, dot, dash, dot),  # AR - OUT - end of message
    "AS":(dot, dash, dot, dot, dot),   # AS - WAIT - I must pause for a few minutes
    "VE":(dot, dot, dot, dash, dot),   # VE - VERIFIED - message is verified
    "BT":(dash, dot, dot, dot, dash),  # BT - BREAK - start new section
    "KA":(dash, dot, dash, dot, dash), # KA - ATTENTION - new message
    "SK":(dot, dot, dot, dash, dot, dash), # SK - OUT - end of contact
}


def morse_char(c):
    if c == " ":
        time.sleep(wspace - lspace)
    else:
        try:
            for t in MORSE_CHARS[c]:
                simpleio.tone(PIEZO_PIN, MORSE_PITCH, duration=t)
                time.sleep(dot)
        except KeyError:
            # unknown character
            simpleio.tone(PIEZO_PIN, MORSE_PITCH/3, duration=dot)


RE_PROSIGN_START = re.compile("<")
RE_PROSIGN_END = re.compile(">")
def morse(string):
    first, *rest = RE_PROSIGN_START.split(string, 1)
    # rest is a list of length 0 or 1
    
    for c in first.upper():
        morse_char(c)
        time.sleep(lspace)

    # send a prosign
    if rest:
        prosign, *rest = RE_PROSIGN_END.split(rest[0], 1)
        # rest is a list of length 0 or 1
        morse_char(prosign.upper())
        time.sleep(lspace)
    
    # send what's after the prosign
    if rest:
        # recursion!  seems an appropriate solution to handle an
        # arbitrary number of embedded prosigns
        morse(rest[0])
        