
# see https://pypi.org/project/openai/
import serial
import time

CRLF = "\r\n"
MAXLINELEN = 71

serialPort = None
# Test under Win10 with remote putty and USB-RS232 adapter (can not do 110)
# serialPort = serial.Serial("COM7", 300, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, 0, True)

# ASR-33 on RPi Zero
#serialPort = serial.Serial("/dev/ttyAMA0", 110, serial.SEVENBITS, serial.PARITY_EVEN, serial.STOPBITS_TWO, 0, True)

def noUmlauts(s):
    result = s.replace('ä', 'ae')
    result = result.replace('ö', 'oe')
    result = result.replace('ü', 'ue')
    result = result.replace('Ä', 'Ae')
    result = result.replace('Ö', 'Oe')
    result = result.replace('Ü', 'Ue')
    result = result.replace('ß', 'ss')
    return result

# to stdout or a serial device
def printString(line):
    if serialPort == None:
        print(line)
    else:
        serialPort.write(line.encode())

# prompt without CRLF at end
def printUserPrompt():
    prompt = "chatGPT>>> "
    if serialPort == None:
        print(prompt, end="")
    else:
        serialPort.write(prompt.encode())

# Get chatGPT input text or local command
# from stdin or a serial device
# line editing with backspace for ASR-33
def getUserCommand():
    if serialPort == None:
        # use python line editor
        command = input()
        return command

    # Serial: own input line editor
    ready = False ;
    command = ""
    serialPort.timeout=0
    while not ready:
        c = serialPort.read() # returns 1 char only
        n = int.from_bytes(c, "little") # n now ascii value
        if n == 0:
            time.sleep(0.01) # 10 ms
            continue # nothing read
        # print (c, n) debug
        if n >= 32 and n < 127: # printable char
            command = command + c.decode() # bytes to string
            serialPort.write(c)
        elif n == 127 or n == 8: # DEL or backspace ^H
            n = len(command)
            if n > 0: # remove last char
                c = command[n-1:] # split off last char
                command = command[:n-1]
                serialPort.write(b"\\") # echo backslash
                serialPort.write(c.encode())
        elif c == b'\r' or c == b'\n': # cr or lf or what?
            ready = True

    # remove leading & trailing white space
    command = command.strip(" \t")
        #command = serialPort.readline() # until \n, timeout?
    return command

# print single or multi line response
# Breaks long lines, see MAXLINELEN
def printResponse(response):
    response = response.split("\n") # now a list of strings
    for line in response:
        line = noUmlauts(line)
        # split each line at 80 char border
        shortline = ""
        words = line.split(" ") ;
        for word in words:
            if len(shortline) + len(word) + 1 >= MAXLINELEN:
                # line full: break
                printString(shortline +CRLF)
                shortline=word
            else: # line not full: add word
                shortline = shortline + " " + word
        if len(shortline) > 0:
            printString(shortline + CRLF) # print trailing words



def isExitCommand(command):
    result = False ;
    if command.lower() == "bye":
            result = True
    if command.lower() == "exit":
            result = True
    if command.lower() == "quit":
            result = True
    return result


openAiClient = 0
def openAiConnect():
    printString ("Connecting to OpenAI ..."+ CRLF)
    from openai import OpenAI

    global openAiClient
    openAiClient = OpenAI(
      api_key="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",
    )

# one chat
def openAiResponse(userCommand):
    completion = openAiClient.chat.completions.create(
         model="gpt-3.5-turbo",
         messages=[
            {"role": "user", "content": userCommand}
          ]
    )
    return completion.choices[0].message.content


#####################
# input loop for user.
if serialPort != None: # serial terminal/ASR33
    CRLF = "\r\n"
    msg = "Serial port " + serialPort.port + " open." + CRLF
    print(msg) ;
    serialPort.write((CRLF + msg).encode())
else:
    CRLF = "\r"
    print("Communicating over Python console") ;

ready = False
openAiConnect()

printString ("Enter questions, until bye, exit or quit. Correct with DEL, Backspace."+CRLF)

while not ready:
    
    # ignore empty input, white space already removed
    printUserPrompt()
    userCommand = ""
    while userCommand == "":
        userCommand = getUserCommand()
        
    printString(CRLF)

    ready = isExitCommand(userCommand)
    if not ready:
        chatResponse = openAiResponse(userCommand)

        printResponse(chatResponse)
        # print(completion.usage.total_tokens)

printString ("Bye!")

