from itertools import cycle
import string
alpha = string.ascii_lowercase

plainText = input("Enter your plaintext to be encrypted: ")
userKey = input("Enter your alphabetical key; exits on invalid character: ").lower()
cipherText = ''
cycKey = cycle(userKey)

# Caesar/ROT Function

def rotateChar(s: str, rotate: int):
  out = ''
  boolUpper = s.isupper()
  s = s.lower()
  if s not in alpha:
    out = s
  elif s in alpha and alpha.index(s) + rotate > 25:
    if boolUpper:
      out = alpha[((alpha.index(s) + rotate) - 25) - 1].upper()
    else:
      out = alpha[((alpha.index(s) + rotate) - 25) - 1]
  else:
    if boolUpper:
      out = alpha[alpha.index(s) + rotate].upper()
    else:
      out = alpha[alpha.index(s) + rotate]
  return out

# Check validity of key; for demonstration purposes I only accept alphabet characters

for char in userKey:
  if char.lower() not in alpha:
    print("Invalid key; quitting.")
    quit()

# Create nested list(s) with the proper ROT number for each string in the plaintext

refList = []

for char, rot in zip([char for char in plainText if char.lower() in alpha], cycKey):
  if char.lower() in alpha:
    refList.append([char, alpha.index(rot)])

# Iterate through original plaintext and rotate when a legal character is at index 0 of refList then pop index 0.

for char in plainText:
  if refList and char == refList[0][0]:
    cipherText += rotateChar(char, refList[0][1])
    refList.pop(0)
  else:
    cipherText += char

print("Ciphertext:", cipherText)