#!/bin/bash
export LANG=C
export TERM=vt220 

export DIALOGRC=dialogrc

source $(dirname $0)/config

export PRINTDEVICE="/dev/ttyUSB$CLIENTS"
export DEVICE="$PRINTDEVICE"

LOCKFILE=/tmp/c3govlock
TMP=/tmp/$RANDOM
BT="c3gov - v0.5.1.2"

cd $(dirname "$0")

function infoBox() {
  h=8
  w=60
  if [ -n "$3" ]; then
    h=$3
  fi
  if [ -n "$4" ]; then
    w=$4
  fi
  dialog --title "$1" \
  --backtitle "$BT" \
  --infobox "$2" $h $w
}

function diaBox() {
  h=8
  w=60
  if [ -n "$3" ]; then
    h=$3
  fi
  if [ -n "$4" ]; then
    w=$4
  fi
  dialog --title "$1" \
  --backtitle "$BT" \
  --msgbox "$2" $h $w
}

function ynBox() {
  h=8
  w=60
  if [ -n "$3" ]; then
    h=$3
  fi
  if [ -n "$4" ]; then
    w=$4
  fi

  dialog --title "$1" \
  --backtitle "$BT" \
  --yesno "$2" $h $w

  return $?
}

function askStr() {
  h=12
  w=60
  if [ -n "$5" ]; then
    h=$5
  fi
  if [ -n "$6" ]; then
    w=$6
  fi

  dialog --title "$2" \
  --backtitle "$BT" \
  --max-input $1 \
  --inputbox "$3" $h $w "$4" 2> $TMP
  return $?
}

function askPw() {
  h=12
  w=60
  if [ -n "$5" ]; then
    h=$5
  fi
  if [ -n "$6" ]; then
    w=$6
  fi

  dialog --title "$2" \
  --backtitle "$BT" \
  --max-input $1 \
  --insecure \
  --passwordbox "$3" $h $w "$4" 2> $TMP
  return $?
}

function confirm() {
  h=12
  w=60
  if [ -n "$3" ]; then
    h=$3
  fi
  if [ -n "$4" ]; then
    w=$4
  fi

  dialog --title "Confirm: $1" \
  --backtitle "$BT" \
  --yesno "Please confirm those information:\n$2" $h $w
  return $?
}

function askStrThird() {
  h=12
  w=60
  if [ -n "$6" ]; then
    h=$5
  fi
  if [ -n "$7" ]; then
    w=$6
  fi

  dialog --backtitle "$BT" \
    --max-input $1 \
    --title "$2" \
    --extra-button --extra-label "$4" \
    --inputbox "$3" $h $w "$5" 2> $TMP
  return $?
}

function gpgSearch() {
  askStr 255 "GPG Search" "Type in the mail address you'd like to look up on keys.openpgp.org."
  if [ $? -eq 0 ]; then
    if [[ "$(cat $TMP)" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$ ]]; then
      clear
      echo "Searching for GPG key..."
      gpg --keyserver "hkps://keys.openpgp.org" --search "$(cat $TMP)"
      if [ $? -eq 0 ]; then
        FFP=$(gpg -k "$(cat $TMP)" | head -n 2 | tail -n 1 | awk '{print $1}' | sed 's/.\{4\}/& /g;s/^\(.*\) $/\1/g')
        gpg --batch --delete-key "$FFP"
        if [ "$FFP" = "" ]; then
          diaBox "GPG Search" "No fingerprint has been found for $(cat $TMP)"
          return 1
        else
          return 0
        fi
      else
        diaBox "GPG Search" "No fingerprint has been found for $(cat $TMP)"
        return 1
      fi
    else
      diaBox "GPG Search" "This is on vaild mail address."
      return 1
    fi
  fi
  return 1
}

function enterGPG() {
  askStrThird 49 "GPG Fingerprint" "Enter GPG fingerprint WITH SPACES. E.g.:\n 1234 5678 9ABC DEF0 1234 5678 9ABC DEF0 1234 5678" "Search..." "$1"

  ret=$?
  case $ret in
    0)
      FP=$(cat $TMP)
      rm $TMP
      if ! [[ $FP =~ ^([[:xdigit:]]{4} ){9}[[:xdigit:]]{4}$ ]]; then
        diaBox "GPG Fingerprint" "This does not match the RegEx of a GPG fingerprint.\nPlease type in the whole fingerprint."
        enterGPG
      fi
      FP=$(echo "$FP" | tr [a-f] [A-F])
      ;;
    1)
      return 1
      ;;
    3)
      gpgSearch
      if [ $? -eq 0 ]; then
        enterGPG "$FFP" "no-confirm"
        return 0
      else
        return 1
      fi
      ;;
  esac

  if [ "$2" == "no-confirm" ]; then
    return 0
  else
    confirm "GPG Fingerprint" "  GPG:\n    $FP"
    return $?
  fi
}

function checkLockFile() {
  while [ -f $LOCKFILE ]; do
    infoBox "Printer is in use..." "Printer is in use. Please wait."
    sleep 1
  done
  touch $LOCKFILE
}

function printGPG() {
  askForField "GPG fingerprint" "$1"
  if [ $? -eq 0 ]; then
    checkLockFile
    diaBox "Insert Passport" "Please insert passport (Visas) into the printer."
    cd "$1"
    ./gpgkey $FIELD $FP
    cd ..
    rm $LOCKFILE
    return 0
  else
    return 1
  fi
}

function printReg() {
  checkLockFile
  diaBox "Insert Passport" "Please insert passport (First page, name, place) into the printer."
  cd "$1"
  ./reg "$FNAME" "$SNAME" "$PLANET"
  cd ..
  rm $LOCKFILE
  return 0
}

function printc3govStamp() {
  askForField "c3gov stamp" "$1"
  if [ $? -eq 0 ]; then
    checkLockFile
    diaBox "Insert Passport" "Please insert passport (Visas) into the printer."
    cd "$1"
    ./c3gov $FIELD
    cd ..
    rm $LOCKFILE
    return 0
  else
    return 1
  fi
}

function askForField() {
  declare -A layout
  declare -A maxfield
  text="$1: Please choose a free field on the passport.\n"

  layout[jhp]="
  ------------------\n 
  | Archievements  |\n
  ==================\n
  | 0 | 1 || 6 | 7 |\n
  |---|---||---|---|\n
  | 2 | 3 || 8 | 9 |\n
  |---|---||---|---|\n
  | 4 | 5 || 10| 11|\n
  ==================\n
  "
  
  layout[bounddipl]="
  ------------------\n 
  | VISAS || VISAS |\n
  ==================\n
  | 0 | 1 || 4 | 5 |\n
  |---|---||---|---|\n
  | 2 | 3 || 6 | 7 |\n
  ==================\n
  "

  layout[stapleddipl]="
  ------------------\n
  | VISAS || VISAS |\n
  ==================\n
  | 0 | 1 || 4 | 5 |\n
  |---|---||---|---|\n
  | 2 | 3 || 6 | 7 |\n
  ==================\n
  "


  maxfield[jhp]=11
  maxfield[bounddipl]=7
  maxfield[stapleddipl]=7

  askStr 2 "Select a field" "$text ${layout[$2]}" "" 18
  if [ $? -eq 1 ]; then
    return 1
  fi
  FIELD=$(cat $TMP)
  if ! [[ "$FIELD" =~ ^[0-9]+$ ]] || [ -z "$FIELD" ] || [ $FIELD -lt 0 ] || [ $FIELD -gt ${maxfield[$2]} ]; then
    askForField "$1" "$2"
  else 
    return 0
  fi
}


function askReg() {
  # Max length of passport fields
  declare -A MAXLENGTH
  MAXLENGTH[jhp]=25
  MAXLENGTH[bounddipl]=17
  MAXLENGTH[stapleddipl]=17
  MAXLENGTH[stapled_glossy_dipl]=17

  askStr ${MAXLENGTH[$1]} "Forename/Nickname" "Enter forename/nickname"
  if [ $? -eq 1 ]; then
    return 1
  fi
  FNAME=$(cat $TMP)

  askStr ${MAXLENGTH[$1]} "Surname" "Enter surname"
  if [ $? -eq 1 ]; then
    return 1
  fi
  SNAME=$(cat $TMP)

  askStr ${MAXLENGTH[$1]} "Place" "Enter place"
  if [ $? -eq 1 ]; then
    return 1
  fi
  PLANET=$(cat $TMP)

  confirm="  Forename:  $FNAME\n  Surname:  $SNAME\n  Place:    $PLANET"

  ynBox "Security" "Secure this passport using security stickers?"
  if [ $? -eq 0 ]; then
    SECURE=true
  else
    SECURE=false
  fi

  ynBox "c3gov Stamp" "Does this entity want to have a c3gov stamp?"
  if [ $? -eq 0 ]; then
    STAMP=true
  else
    STAMP=false
  fi

  ynBox "GPG" "Does the entity have a GPG key to register?"
  if [ $? -eq 0 ]; then
    enterGPG "" no-confirm
    if [ $? -eq 0 ]; then
      confirm="$confirm\n  GPG:\n    $FP"
    fi
  fi

  confirm "Everything" "$confirm"
  return $?

}

function enterSecurityCode() {
  MAXLENGTH=6

  askStr ${MAXLENGTH} "Security code" "Enter security code from the security sticker (e.g. S12345)."
  if [ $? -eq 1 ]; then
    return 1
  fi
  SECURITYCODE=$(cat $TMP)
  confirm "Security code" "Security code: $SECURITYCODE"
  return $?

}

function printSecurePassportFirstPage(){
  checkLockFile
  diaBox "Insert Passport" "Pleast insert the FIRST PAGE (Identity) into the printer."

  cd "$1"
  ./secure_firstpage "$SECURITYCODE"
  cd ..
  rm $LOCKFILE
}

function printSecurePassport(){
  checkLockFile
  diaBox "Insert Passport" "Please insert passport (Visas) into the printer.\nA print on EVERY Visa page is necessary."

  cd "$1"
  ./secure "$SECURITYCODE"
  cd ..
  rm $LOCKFILE
}

function enableSecurity() {
  if [ "$1" = "bounddipl" ]; then
    diaBox "Error" "Passport security: Passport not supported."
  else
    enterSecurityCode
    if [ $? -eq 0 ]; then
      case $1 in
        "bounddipl")
        ;;
        "jhp")
          printSecurePassport "$1"
        ;;
        *)
          printSecurePassportFirstPage "$1"
          printSecurePassport "$1"
        ;;
      esac
    fi
  fi
}

function menuFor() {
  dialog --backtitle "$BT" \
  --menu "Select purpose:" 14 40 3 \
  1 "Registration" \
  2 "c3gov Stamp" \
  3 "GPG" \
  8 "Secure Passport" \
  9 "Back" 2> $TMP
 
  choice=$(cat $TMP)

  case $choice in
    1)  askReg "$1"
        if [ $? -eq 0 ]; then
          printReg "$1"
          if [ "$SECURE" = "true" ]; then
            enableSecurity "$1"
          fi
          if [ "$STAMP" = "true" ]; then
            printc3govStamp "$1"
          fi
          if [ -n "$FP" ]; then
            printGPG "$1"
          fi
        fi
        ;;
    2)  printc3govStamp "$1"
        ;;
    3)  enterGPG
        if [ $? -eq 0 ]; then
          printGPG "$1"
        fi
        ;;
    8)  enableSecurity "$1"
        ;;

  esac

  unset FNAME
  unset SNAME
  unset PLANET
  unset FP
  unset FIELD
  unset FFP
  unset SECURITYCODE
}

function askForFunnyUserCreds() {
  clear
  echo "Press Enter to start."
  read -s

  askStr 12 "Login" "Username:" ""
  username=$(cat $TMP)
  askPw 12 "Login" "Password:" ""
  password=$(cat $TMP)

  if [ -f ".pw/$username" ]; then
    if [ "$password" != $(cat .pw/$username) ]; then
      clear
      echo "Wrong credentials."
      sleep 3
      exit 1
    fi
  else
    echo "Wrong credentials."
    sleep 3
    exit 1
  fi
}

askForFunnyUserCreds

while [ true ]; do

  dialog --backtitle "$BT" \
    --menu "Select ID type:" 12 40 3 \
    1 "Stapled diplomatic passport" \
    2 "Stapled glossy paper diplomatic passport" \
    3 "Junghackerpass" \
    4 "Bound diplomatic passport" \
    9 "Logout" 2> $TMP

  if [ $? -eq 9 ]; then
    break
  fi
  
  TYPE=$(cat $TMP)


  case $TYPE in
    1)  menuFor stapleddipl
        ;;
    2)  menuFor stapled_glossy_dipl
        ;;
    3)  menuFor jhp
        ;;
    4)  menuFor bounddipl
        ;;
    9)  break
        ;;
  esac
done

rm $TMP
clear
