#!/bin/bash -eu
# baca ; BAsh CAesar cipher ; notices and documentation at the end of the file

main () {
 check_arguments
 cipher
 exit 0
}

#------------------------------------------------#-------------------------------------------#
check_arguments () {                             # global variable: cline key
 local readonly prog=${cline[0]##*/}             # program name - basename
 local readonly argc=$((${#cline[*]} - 1 ))      # argument count

 if [ $argc -lt 2 ] ; then                       # at least: key one_word
  echo $prog: error, wrong number of arguments >&2
  usage $prog
  exit 1
 fi

 key=${cline[1]}

 if ( [ "$key" -lt 0 ] || [ "$key" -gt 25 ] ) ; then
  echo $prog: error, key out of range >&2
  usage $prog
  exit 2
 fi
}

#------------------------------------------------#-------------------------------------------#
usage () {
 printf "\
usage: $1 key some text
where key is 0 to 25
example: $1 2 Hello world 
" >&2                                            # redirected to stderr
}

#------------------------------------------------#-------------------------------------------#
cipher () {                                      # global variables: key text
 local readonly s1=${cline[*]}                   # whole command line
 local readonly s2=${s1#* }                      # remove first word
 local readonly text=${s2#* }                    # plain text, after removing second word
 local readonly an=$(($key+65))                  # an=66 ; numeric value ; with key=1
 local readonly bn=$(($key+66))                  # bn=67 ; follow-up character
 local readonly a=$(printf "\x$(printf %x $an)") # a=B   ; character value
 local readonly b=$(printf "\x$(printf %x $bn)") # b=C
 echo "$text" | tr a-z A-Z | tr A-Z $a-ZA-$b     # to upper case | rotate only character A-Z, others unchanged
}                                                # not modulus https://en.wikipedia.org/wiki/Modular_arithmetic

#--------------------------------------------------------------------------------------------#
declare -a readonly cline=($0 $@)                # command line; e.g., prog arg1 argN
main ; echo Error: sentinel ; exit 1

#--------------------------------------------------------------------------------------------#
# usage: baca key some text
#  where key is 0 to 25
# example: baca 1 Hello World
# key=0 no cipher
# https://en.wikipedia.org/wiki/Caesar_cipher
#
# The same program without error checking:
#   key=$1
#   shift
#   text="$*"
#   an=$(($key+65))
#   bn=$(($key+66))
#   a=$(printf "\x$(printf %x $an)")
#   b=$(printf "\x$(printf %x $bn)")
#   echo "$text" | tr a-z A-Z | tr A-Z $a-ZA-$b
#
# ROT13
# Particular case with key=13
# https://en.wikipedia.org/wiki/ROT13
# baca 13 hello
# baca 13 $(baca 13 hello)
# echo Hello | tr A-Za-z N-ZA-Mn-za-m # output:Uryyb
# echo Uryyb | tr A-Za-z N-ZA-Mn-za-m # output:Hello
#
# latest version at: dragoman.org/baca
# Rights: CC BY-SA - Creative Commons Attribution-ShareAlike
## M.T. Carrasco Benitez | ca@dragoman.org | 2022-10-03
