#!/bin/sh

# Flip-file shell script version 1 by Ben Collver
# Roughly based on FLIP.BAS.
#
# <gopher://tilde.pink/0/~bencollver/log/
# 2025-07-14-occ-freebasic-qbasic-and-wm-tweaks/flip.bas>

cardfile="FLIP.DAT"
exported="flip.tsv"

# maximum number of cards
mx=30

# maximum line length (80 - 9 - 3)
il=68

# current card number
card=1

# number of last card in file
last=0

# flag for deleted card
delmsg="' CARD DELETED '"

type mktemp >/dev/null 2>&1
if [ $? -eq 127 ]
then
   mktemp()
   {
       o=0
       s=$(date +%s)
       while [ $o -lt 100 ]
       do
           t=$(echo $(($o + $s)) | md5sum | cut -c 1-6)
           f="/tmp/tmp.$t"
           if [ ! -f "$f" ]
           then
               break
           fi
           o=$(($o+1))
       done
       if [ -f "$f" ]
       then
           exit 127
           return 127
       else
           touch "$f"
           echo "$f"
       fi
       return 0
   }
fi

# session data file
f=$(mktemp)

# helper script file
helper=$(mktemp)

# output from dialog command
RESULT=$(mktemp)

# remove tempfiles on exit
trap "rm -f $f $helper $RESULT" 0

export DIALOGOPTS="--no-mouse --title Flip-file"

echo "form_item_readonly_color = (WHITE,BLUE,ON)" >flip.rc

append_record()
{
   infile=$1

   awk -F "\n" -v OFS="\t" -v ORS="\r\n" -v RS="\xFF" '{
print $1, $2, $3, $4, $5, $6, $7
   }' $infile >>$f

   return
}

add_card()
{
   limit=$((mx - 1))
   if [ $last -eq $limit ]
   then
       dialog --backtitle "$backtitle" \
           --msgbox "File full. Save cards." 0 0
       return
   fi

   card=$((last + 1))
   last=$((last + 1))
   backtitle=$(get_backtitle)
   dialog --backtitle "$backtitle" \
       --no-cancel                 \
       --ok-label "Back"           \
       --form "Add a card" 0 -1 7  \
       Name:   1 1 "" 1 10 60 $il  \
       Street: 2 1 "" 2 10 60 $il  \
       Town:   3 1 "" 3 10 60 $il  \
       County: 4 1 "" 4 10 60 $il  \
       Code:   5 1 "" 5 10 60 $il  \
       Phone:  6 1 "" 6 10 60 $il  \
       Info:   7 1 "" 7 10 60 $il  \
       2>$RESULT
   EXITCODE=$?

   case $EXITCODE in
   255) exit                  ;;
     0) append_record $RESULT ;;
    -1) error_exit $RESULT    ;;
   esac

   return
}

browse()
{
   while :
   do
       backtitle=$(get_backtitle)
       cat >$helper <<__EOF__
DIALOGRC=flip.rc dialog                     \\
   --backtitle "$backtitle"                \\
   --extra-button                          \\
   --help-button                           \\
   --ok-label Previous                     \\
   --extra-label Next                      \\
   --cancel-label Search                   \\
   --help-label Back                       \\
   --form "Browse & search" 0 -1 7         \\
__EOF__
       view_card_fields $card -60 $helper
       echo "    2>$RESULT" >>$helper
       sh $helper
       EXITCODE=$?

       case $EXITCODE in
       255) exit                                      ;;
         3) [ $card -lt $last ] && card=$((card + 1)) ;;
         2) break                                     ;;
         1) search                                    ;;
         0) [ $card -gt 1 ]     && card=$((card - 1)) ;;
        -1) error_exit $RESULT                        ;;
       esac
   done
   return
}

del_card()
{
   update=$(mktemp)
   backtitle=$(get_backtitle)
   while :
   do
       cat >$helper <<__EOF__
DIALOGRC=flip.rc dialog           \\
   --backtitle "$backtitle"      \\
   --cancel-label Back           \\
   --ok-label Delete             \\
   --form "Remove a card" 0 -1 7 \\
__EOF__
       view_card_fields $card -60 $helper
       echo "    2>$RESULT" >>$helper
       sh $helper
       EXITCODE=$?

       case $EXITCODE in
       255) exit               ;;
         1) break              ;;
        -1) error_exit $RESULT ;;
       esac

       awk -F "\t" -v RS="\r\n" -v OFS="\t" -v ORS="\r\n" \
           -v card=$card -v delmsg="$delmsg" '
NR != 1 + card {print $0}
NR == 1 + card {print $1, $2, $3, $4, $5, $6, delmsg}
' $f >$update

       cat $update >$f
   done

   rm -f $update
   return
}

edit_card()
{
   backtitle=$(get_backtitle)
   cat >$helper <<__EOF__
dialog --backtitle "$backtitle" \\
   --no-cancel                 \\
   --ok-label Back             \\
   --form "Edit a card" 0 -1 7 \\
__EOF__
   view_card_fields $card 60 $helper
   echo "    2>$RESULT" >>$helper
   sh $helper
   EXITCODE=$?

   case $EXITCODE in
   255) exit                  ;;
     0) update_record $RESULT ;;
    -1) error_exit $RESULT    ;;
   esac

   return
}

error_exit() {
   RESULT="$1"
   printf "Error: "
   cat $RESULT
   exit
}

find_record()
{
   infile=$1
   outfile=$(mktemp)
   pos=0
   backtitle=$(get_backtitle)

   term=$(awk -v OFS="\t" '{
   if (length($0) > 0) {
       print NR, $0
       exit
   }
}' $infile)

   while :
   do
       awk -F "\t" -v RS="\r\n" -v pos=$pos -v term="$term" '
BEGIN {
   OFS = FS
   found = 0
   nextpos = 0
   num = split(term, fields, /\t/)
   if (num == 2) {
       field = fields[1]
       value = fields[2]
   } else {
       field = 1
       value = ""
   }
}

{
   result = 0
   if (length(value) > 0) {
       if (value == $field) {
           result = 1
       }
   }
   if (result == 1) {
       found++
       if (nextpos == 0 && NR - 1 > pos) {
           nextpos = NR - 1
       }
       lastpos = NR - 1
   }
}

END {
   if (nextpos == lastpos) {
      islast = 1
   } else {
      islast = 0
   }
   print nextpos, found, islast, value
}' $f >$outfile

       pos=$(cat $outfile    | cut -f 1)
       found=$(cat $outfile  | cut -f 2)
       islast=$(cat $outfile | cut -f 3)
       value=$(cat $outfile  | cut -f 4)
       if [ $found -eq 0 ]
       then
           dialog --backtitle "$backtitle" \
               --msgbox "Didn't find: $value" 0 0
           break
       else
           card=$pos
           backtitle=$(get_backtitle)
           cat >$helper <<__EOF__
DIALOGRC=flip.rc dialog                   \\
   --backtitle "$backtitle"              \\
   --ok-label Next                       \\
   --cancel-label Back                   \\
   --form "Searching for $value " 0 -1 7 \\
__EOF__
           view_card_fields $card -60 $helper
           echo "    2>$RESULT" >>$helper
           sh $helper
           EXITCODE=$?

           case $EXITCODE in
           255) exit               ;;
             1) break              ;;
             0)
                if [ $islast -eq 1 ]
                then
                    msg="Search over\nFound: $found times"
                    dialog --backtitle "$backtitle" \
                        --msgbox "$msg" 0 0
                    break
                fi
                ;;
            -1) error_exit $RESULT ;;
           esac
       fi
   done
   rm -f $outfile
   return
}

get_backtitle()
{
   if [ $last -eq 0 ]
   then
       echo "No cards in file"
   elif [ $last -gt 0 ]
   then
       if [ $card -lt $((mx + 1)) ]
       then
           echo "$last cards on card $card "
       else
           echo "$last cards"
       fi
   fi
   return
}

load()
{
   last=$(awk -v RS="\r\n" 'NR == 1 {print $1}' $cardfile)
   card=1

   printf "Name\tStreet\tTown\tCounty\tCode\tPhone\tInfo\r\n" >$f

   awk -F "\t" -v RS="\r\n" -v OFS="\t" -v ORS="\r\n" '
NR > 1 {
   name=$0
   getline street
   getline town
   getline county
   getline code
   getline phone
   getline info
   print name, street, town, county, code, phone, info
}' $cardfile >>$f

   return
}

save()
{
   # write count of not-deleted records

   awk -F "\t" -v RS="\r\n" -v ORS="\r\n" -v delmsg="$delmsg" '
NR > 1 {
   if ($7 != delmsg) {
       notdel++
   }
}
END {
   print notdel
}' $f >$cardfile

   # write lines for not-deleted records

   awk -F "\t" -v RS="\r\n" -v OFS="\r\n" -v ORS="\r\n" \
   -v delmsg="$delmsg" '
NR > 1 {
   if ($7 != delmsg) {
       print $1, $2, $3, $4, $5, $6, $7
   }
}' $f >>$cardfile

   cat $f >$exported

   echo "Cards saved. You are no longer in Flip-file."
   exit 0
}

search()
{
   backtitle=$(get_backtitle)
   dialog --backtitle "$backtitle" \
       --no-cancel                 \
       --ok-label "Search"         \
       --form "Search" 0 -1 7      \
       Name:   1 1 "" 1 10 60 $il  \
       Street: 2 1 "" 2 10 60 $il  \
       Town:   3 1 "" 3 10 60 $il  \
       County: 4 1 "" 4 10 60 $il  \
       Code:   5 1 "" 5 10 60 $il  \
       Phone:  6 1 "" 6 10 60 $il  \
       Info:   7 1 "" 7 10 60 $il  \
       2>$RESULT
   EXITCODE=$?

   case $EXITCODE in
   255) exit                ;;
     0)
        find_record $RESULT
        break
        ;;
    -1) error_exit $RESULT  ;;
   esac

   return
}

update_record()
{
   infile=$1
   record=$(mktemp)
   update=$(mktemp)

   awk -F "\n" -v OFS="\t" -v RS="\xFF" '{
print $1, $2, $3, $4, $5, $6, $7
}' $infile >$record

   rec=$(cat $record)

   awk -F "\t" -v RS="\r\n" -v ORS="\r\n" -v card=$card \
       -v rec="$rec" '
NR != 1 + card {print $0}
NR == 1 + card {print rec}
' $f >$update

   cat $update >$f
   rm -f $record $update
   return
}

view_card_fields()
{
   pos="$1"
   len="$2"
   out="$3"

   awk -F "\t" -v RS="\r\n" -v ORS="\r\n" -v card=$pos \
       -v len=$len -v il=$il '
NR == 1 {
   for (i = 1; i <= NF; i++) {
       name[i] = toupper(substr($i, 1, 1)) substr($i, 2) ":"
   }
}
NR == 1 + card {
   for (i = 1; i <= NF; i++) {
       q = "\"" $i "\""
       printf "%-7s %d 1 %-9s %d 10 %d %d \\\n",
           name[i], i, q, i, len, il
   }
}' $f >>$out

   return
}

# ==================================================================

main() {
   printf "Name\tStreet\tTown\tCounty\tCode\tPhone\tInfo\r\n" >$f
   while :
   do
       backtitle=$(get_backtitle)
       dialog --backtitle "$backtitle"             \
           --no-cancel                             \
           --menu "Would you like to:" 0 0 7       \
           ADD    "Add a card"                     \
           REMOVE "Remove a card"                  \
           ALTER  "Alter a card (edit/update)"     \
           BROWSE "Flip cards (browse/search)"     \
           LOAD   "Load cards"                     \
           SAVE   "File these cards (save & quit)" \
           2>$RESULT
       EXITCODE=$?

       case $EXITCODE in
       255) exit               ;;
        -1) error_exit $RESULT ;;
       esac

       OUTPUT=$(cat $RESULT)

       if [ "$OUTPUT" != "ADD" -a "$OUTPUT" != "LOAD" ]
       then
           if [ $last -eq 0 ]
           then
               dialog --backtitle "$backtitle" \
                   --msgbox "No cards in file" 0 0
               continue
           fi
       fi

       case "$OUTPUT" in
       REMOVE) del_card  ;;
       ADD)    add_card  ;;
       ALTER)  edit_card ;;
       BROWSE) browse    ;;
       LOAD)   load      ;;
       SAVE)   save      ;;
       esac
   done
   exit 0
}

main