#!/bin/bash 

# one more addressbook
# 2008 by Lukas Gantert, GPL
# 20081214 sync PC > Palm
# 20081220 in edit mode, can now show the old field-text
# 20090117 in search-dialog, can now repeat the search-string (bash-only)
# 20091119 improved print-function
# 20091216 allows search pattern on the command-line (saving two keystrokes for a search!)
# 20110108 change to utf8, even the palm-sync with 'recode' (palm is always latin1)

TODO='
- internationalisation, first: en - de - fr

- put the configuration in a separate configuration file

- bug: when one result in search ?

- complete the help-section

- bug: when Feldtrenner in text, sync PC>Palm fails

- bug: palmsync: einseitig entfernte Einträge werden nicht entfernt

- clean up the code
'
# substitution of: CMD=$(basename "$0")
CMD="${0##*/}"

# set the terminal title
printf '\033]2;%s\007' "$CMD"

version=20091216

FILE="$HOME/.schelladressen"
TMPFILE=/tmp/adressentemp$$
TMPFILE_1=/tmp/adressentemp_1$$
MailTo='claws-mail --compose'
BROWSER=${BROWSER:-"/usr/bin/epiphany-gecko"}
DELIM='%%'

# if $CMD is called with arguments (search-strings)
PATTERN1="$1"
PATTERN2="$2"
PATTERN3="$3"
PATTERN4="$4"
NBR_CMD_LINE_ARGS=$#

# Vars for PDA_Sync
PDA_DEVICE='usb:'
PDB_NAME=DB4A-Adressen
PDB_FILE="$PDB_NAME".pdb
CSV_FILE=/tmp/adressen.csv$$
IFO_FILE="$CSV_FILE".ifo
TMP_DIR=/tmp
PWD_OLD="$PWD"

# Vars for the Print - function
printer=${PRINTER:-"laserjet"}
full_username="$(awk -F: -v name=$USER 'gsub(/\,.*$/, ""){ if ($1==name) print $5}' /etc/passwd)"


# please no spaces in field-names!
FIELDS="nom \
prénom \
fonction \
mots-de-clef \
entreprise \
catégorie \
eMail \
maison \
Fax \
natel \
travail \
adresse \
www \
lieu \
canton \
CP \
pays \
titre \
note"

# for sync with gpilotd (evolution):
#FIELDS="Last_name \
#First_name \
#Title \
#Company \
#Office \
#Home \
#Mobile \
#EMail \
#Fax \
#Address \
#City \
#State \
#Zip_Code \
#Country \
#Web \
#Fonction \
#Mot_clef \
#Custom_4 \
#Note \
#Private \
#Category"

# END configuration

Hrule () {
   printf "%$(tput cols)s\n" '' | tr ' ' -
}

# Help
# ####
function Help () {
man -l -- - << EOF
.TH $CMD 1 $VERSION
.UC 4 
.SH NAME
$CMD \- one more address-book

.SH SYNOPSIS
.B $CMD
[searchpatterns (max 4)]

.SH DESCRIPTION
.I $CMD
is a interactive command-line address-book with many features:
full-text-search,
secure edit,
print,
sync with a palm-device,
call the webbrowser to show a webpage,
call the mailerprogram to mail.
The aim is simplicity an robustness.

.SH ACTIONS
.SS insert
With this action you are asked to enter a string for each field (like name, phone) of an new entry.
If done, you ar asked if you want put te new entry in the database.
In any case, you can modify the entry later (see edit in the 'ENTRY_ACTIONS'-section
of this manual page).

.SS search
Search for one or more address-book-entrys by a full text search.
Up to 4 search-patterns are allowed, also in the Form of regular expressions
(put them in doubble quotes)

.SS sync
Sync with a palm device. The 'pilot-db' programm must be installed on the handheld.

.SS export
To export the hole adress-database to a comma-separated text file,
ready for import in a spread-sheet programm like 'openoffice-calc',
'gnumeric' or 'Excel'.

.SS help
Type h for help (to show this man-page).

.SS quit
Type q for quit.

.SH ENTRY-ACTIONS
xyz

.SS edit
xyz

.SS mail
xyz

.SS web
xyz

.SS print
xyz

.SS next
xyz

.SS delete
xyz

.SH FILES
The default datafile is  $FILE.
It can be usefull to edit this file with a text editor  if you want to import addresses from other databases. It is the only way to do, for now. Take care to respect the field-deliminator (actually "$DELIM") and the number of fields.
.PP
For now, all the settings are done in the first section of the script $CMD.
You are completly free to adapt the script to your needs. For example, if you want to change the Number of fields an the field-names.

.SH AUTHOR
Lukas Gantert
http://nofalab.ch

.SH VERSION
$CMD,  $version.

Ce programme est un logiciel libre.
Vous pouvez en redistribuer des copies selon les termes de la
License Publique Générale de GNU, <http://www.gnu.org/licenses/gpl.html>.
AUCUNE GARANTIE n'est fournie tel que permis selon la loi."

.SH BUGS
Please send bug-reports and sugestions to the author.

.SH TODO
$TODO

.SH SEE ALSO
vim, awk, bash.
There is a nice suite of little scripts on the authors homepage.
EOF
Main
}

# VERSION anzeigen
# ################
Version () {
   Hrule
   echo "Voici $CMD, VERSION $version. Écrit par Lukas Gantert.

   Ce programme est un logiciel libre.
   Vous pouvez en redistribuer des copies selon les termes de la
   License Publique Générale de GNU, <http://www.gnu.org/licenses/gpl.html>.
   AUCUNE GARANTIE n'est fournie tel que permis selon la loi."
   Main
}

# Adresseintrag erstellen (input)
# ###############################
Insert () {
   # Felder anzeigen, Einträge entgegennehmen, in temporäre FILE schreiben 
   set -- "$FIELDS"
   #Felderinhalte lesen und schreiben
   for FELD in $@; do
      printf "%+15s: %s" "$FELD"
      read "FELDEINTRAG"
      echo -n "$FELDEINTRAG""$DELIM" >> $TMPFILE
   done
   # Abfrage, ob Eintrag in Ordnung
   Abfrage
}

Abfrage() {
   echo "Angaben in $FILE schreiben? y = ja; n = nein"
   read -s -n 1 ANTWORT

   case "$ANTWORT" in
      y|Y ) sed 's/'"$DELIM"'$/\n/' "$TMPFILE" >> "$FILE"
      echo "Eintrag in $FILE geschrieben."
      rm -f "$TMPFILE" "$TMPFILE_1"
      Main
      ;;
      n|N ) echo "Eintrag nicht geschrieben"
      rm -f "$TMPFILE" "$TMPFILE_1"
      Main
      ;;
      * ) echo "bitte Antwort eingeben!" 
      Abfrage
      ;;
   esac
}

# suchen, anzeigen, editieren, löschen, Mailen und Webseite anzeigen, drucken
# ###########################################################################

Search () {
   # test if there are command-line arguments (search-patterns)
   if [ $NBR_CMD_LINE_ARGS -eq 0 ]; then
      echo -n "SUCHBEGRIFFE: "
      read -e PATTERN1 PATTERN2 PATTERN3 PATTERN4
   fi
   NBR_CMD_LINE_ARGS=0

   ALL_PATTERNS="$(echo $PATTERN1 $PATTERN2 $PATTERN3 $PATTERN4)"
   history -s $ALL_PATTERNS

   # vierfache AND-Suche
   LINES_FOUND="$(awk '{IGNORECASE = 1}
   /'$PATTERN1'/&&/'$PATTERN2'/&&/'$PATTERN3'/&&/'$PATTERN4'/{print NR}' $FILE)"
   RESULTNBR="$(echo "$LINES_FOUND" | wc -w)"
   [ $RESULTNBR == 0 ] &&
   echo "Keinen Eintrag zum Suchmuster \"$PATTERN1 $PATTERN2 $PATTERN3 $PATTERN4\" gefunden!" &&
   Main

   nENTRY=1
   set -- $LINES_FOUND
   for LINE_NUMBER in $*; do
      Show
      let nENTRY+=1
   done
   Main
}

# Eintrag anzeigen
Show () {
   clear
   SHOW_LINE="$(awk -F "$DELIM" 'NR == '$LINE_NUMBER'' $FILE | sed 's/^"//;s/"$//')"
   printf "Ergebnis \e[1m$nENTRY\e[0m von \e[1m$RESULTNBR\e[0m "
   printf "für \e[1m \"$PATTERN1 $PATTERN2 $PATTERN3 $PATTERN4\"\e[0m"
   printf -- " - Linie \e[1m$LINE_NUMBER\e[0m in $FILE\n"
   Hrule
   nFELD=1
   set -- "$FIELDS"
   for FELD in $*; do
      # workaround for alignement with utf8
      # "$((15-${#FELD}..." count chars not bytes
      # merci, Heike C. Zimmerer
      printf "%$((15-${#FELD}-${#nFELD}))s %+3s \e[1m%s\e[0m\n" \
      "" "$FELD($nFELD)" \
      "$(echo "$SHOW_LINE" | awk -F "$DELIM" '{print $'"$nFELD"'}')"
      let nFELD+=1
   done
   Hrule

   # Next-Edit-Delete-Quit-etc--Aktionen-Choreographie
   echo "n:next e:edit m:Mail w:Web p:print d:delete i:insert s:search h:help q:quit"
   read -s -n1  COMMAND
   case $COMMAND in
      n ) NextLine ;;
      e ) EditLine ;;
      m ) Mail ;;
      w ) Web ;;
      p ) ToPrinter ;;
      d ) DeleteLine ;;
      i ) Insert ;;
      s ) Search ;;
      h ) Help ;;
      q ) rm -f $TMPFILE $TMPFILE_1; printf '\033]2;%s\007' "Terminal" ; exit ;;
      [[:upper:]] ) printf "\n$RED%s\n%s$BACK\n\n" "Sorry, there are no capital letters accepted." "is Caps-look activated?"; Main ;;
      * ) Show ;;
   esac
}

Mail () {
   $MailTo 2>/dev/null "$(echo "$SHOW_LINE" |
   awk -F "$DELIM" '{print $7}')" &
   Show
}

Web () {
   $BROWSER 2>/dev/null "$(echo "$SHOW_LINE" |
   awk -F "$DELIM" '{print $13}')" &
   Show
}

ToPrinter () {
   rm -f "$TMPFILE" "$TMPFILE_1"
   nFELD=1
   set -- "$FIELDS"
   for FELD in $*; do
      printf "%$((15-${#FELD}-${#nFELD}))s %+3s %s\n" \
      "" "$FELD($nFELD)" \
      "$(echo "$SHOW_LINE" |
      awk -F "$DELIM" '{print $'"$nFELD"'}')" >> "$TMPFILE"
      let nFELD+=1
   done
   a2ps \
   --encoding=iso-8859-1 \
   --borders=on \
   --center-title="Aus dem Schelladressbuch von $full_username" \
   --left-title="" \
   --right-title="" \
   --left-footer="$(date '+%c')" \
   --footer="" \
   --pretty-print=$LANG \
   --columns=1 \
   --border=on \
   --chars-per-line=110 \
   --landscape \
   --medium=A4 \
   "$TMPFILE" | lp -d $printer
   rm -f "$TMPFILE" "$TMPFILE_1"
   Show
}

# in den Suchergebnissen weiterblättern
NextLine () {
   :
}

# den aktuellen Eintrag editieren (pro Funktions-Aufruf ein Feld)
EditLine () {
   echo -n "Nummer des zu editierenden Feldes eingeben und mit 'Enter' bestaetigen: "
   read FELD_NR
   FIELDNAME="$(echo $FIELDS | awk -F" " '{print $'"$FELD_NR"'}')"
   FIELDCONTENT=$(echo -n "$SHOW_LINE" |
   awk 'BEGIN {FS=OFS="'"$DELIM"'"}{printf $'"$FELD_NR"'}')
   history -s "$FIELDCONTENT" # thanks to Chris F.A. Johnson in c.u.shell (Message-ID: <3954e$494c5482$cef88ba3$1889@TEKSAVVY.COM>
   echo -en "(nach oben-Pfeil druecken um alten Eintrag anzuzeigen) 
   "$FIELDNAME": \033[1m"
   read -e  FELD_ERSATZ
   clear
   echo -e "\033[0mVeränderter Eintrag:"
   Hrule

   CHANGED_LINE="$(echo "$SHOW_LINE" | awk 'BEGIN {FS=OFS="'"$DELIM"'"} {$'$FELD_NR' = "'"$FELD_ERSATZ"'"; print $0}')"

   nFELD=1
   set -- "$FIELDS"
   for FELD in $*; do
      printf "%$((15-${#FELD}-${#nFELD}))s %+3s \e[1m%s\e[0m\n" \
      "" "$FELD($nFELD)" "$(echo "$CHANGED_LINE" | awk -F "$DELIM" '{print $'"$nFELD"'}' | sed 's/^"//;s/"$//')"
      let nFELD+=1
   done
   Hrule
   speichern
}

# Änderung speichern
speichern () {
   echo "Änderung speichern? y:ja n:nein"
   read -s -n1  YN
   if [ $YN = "y" ]; then
      awk -v CHANGED_LINE="$CHANGED_LINE" 'NR=="'$LINE_NUMBER'" {$0=CHANGED_LINE}1' $FILE > $TMPFILE
      mv $TMPFILE $FILE
      rm -f $TMPFILE $TMPFILE_1
      echo "Änderung in "$FILE" gespeichert"
      Show
   elif [ $YN = "n" ]; then
      Show
   else
      echo "speichern?"
      speichern
   fi
}

# den angezeigten Eintrag loeschen
DeleteLine () {
   cp "$FILE" "$FILE"~ #backup
   echo "wirklich löschen? y:ja n:nein"
   read -s -n1 YN
   if [ "$YN" = "y" ]; then
      awk 'NR != '$LINE_NUMBER'' $FILE > $TMPFILE
      mv $TMPFILE $FILE
      rm -f $TMPFILE $TMPFILE_1
      echo "Eintrag gelöscht"
      Main
   else
      rm -f $TMPFILE $TMPFILE_1
      Show
   fi
}

# synchronise with a Palm-device
################################
Palmsync () {
   if whereis pilot-link > /dev/null ; then
      if whereis pdb2csv > /dev/null ; then

         # get data from PDA-device
         cd "$TEMP_DIR"
         pilot-xfer -p "$PDA_DEVICE" -f "$PDB_NAME";

         # convert to a csv-file
         pdb2csv -s "$DELIM" -d "%Y/%m/%d" "$PDB_FILE" "$CSV_FILE" "$IFO_FILE"

         # clean-up the csv-file
         awk '{gsub(/N\/A/, "");
         gsub(/"'$DELIM'"/, "'$DELIM'");
         gsub(/'$DELIM'"/, "'$DELIM'");
         gsub(/"'$DELIM'/, "'$DELIM'");
         gsub(/^"/, "");
         gsub(/"$/, "");
         print}' "$CSV_FILE" | recode latin1..utf8 > "$TMPFILE"

         # merge the data on palm with the data on Desktop
         [ -f "$FILE" ] || touch "$FILE"
         [ -f "$TMPFILE" ] || touch "$TMPFILE"
         sort -u -- "$TMPFILE" "$FILE" > "$TMPFILE_1"
         #backup the old $File
         cp "$FILE" "$FILE"~
         mv "$TMPFILE_1" "$FILE"
         rm  -f "$PDB_FILE" "$TMPFILE" "$TMPFILE_1"

         # put data to PDA
         # Workaround für "sicherern" Feldtrenner
         sed 's/%%/%/g' "$FILE" | recode utf8..latin1 > "$TMPFILE"
         csv2pdb -i "$IFO_FILE" "$TMPFILE" "$PDB_FILE" ;
         sleep 3
         pilot-xfer -p "$PDA_DEVICE" -i "$PDB_FILE"
         rm "$CSV_FILE" "$IFO_FILE" "$PDB_FILE" "$TMPFILE"

         cd "$PWD_OLD"
         Main
      else
         echo "pdb2csv not installed."
         Main
      fi
   else
      echo "pilot-link not installed"
      Main
   fi
}

# $Datei ins CSV-Format exportieren
###################################
Write_csv () {
   # Feldnamen in erste Zeile schreiben
   echo -n "\"$FIELDS" | tr '\n' ' ' | sed 's/ /","/g' > "$CSV_FILE"
   echo "\"" >> "$CSV_FILE"
   # Feldtrenner '%%' in '","' umwandeln
   sed 's/'"$DELIM"'/","/g;s/^/"/;s/$/"/' "$FILE" >> "$CSV_FILE"
   echo "CSV-Export nach "\"$CSV_FILE\"" abgeschlossen!"
}

Export () {
   echo -n "CSV-FILENAME: "
   read CSV_FILE
   if [ -f "$CSV_FILE" ]; then
      echo "$CSV_FILE" exist. Overwrite "$CSV_FILE"? y/n
      read -s -n1 Answer
      if [ $Answer = "y" ]; then
         Write_csv
         Main
      else
         Main
      fi
   else
      Write_csv
   fi
}

# Haupt-Choreographie
#####################
Main () {
   if [ $NBR_CMD_LINE_ARGS -gt 0 ]; then
      Search
   fi
   Hrule
   echo "i:insert  s:search  c:palmsync  e:export  h:help  v:version  q:quit"
   read -s -n1 CHOIX
   case $CHOIX in
      i ) Insert ;;
      s ) Search ;;
      c ) Palmsync ;;
      e ) Export ;;
      h ) Help ;;
      v ) Version ;;
      q ) rm -f $TMPFILE $TMPFILE_1; printf '\033]2;%s\007' "Terminal" ; exit ;;
      [[:upper:]] ) printf "\n$RED%s\n%s$BACK\n\n" "Sorry, there are no capital letters accepted." "is Caps-look activated?"; Main ;;
      * ) Main ;;
   esac
}

Main
rm -f $TMPFILE $TMPFILE_1
exit