#!/bin/bash

# Title......: ab
# Description: Personal address book in CSV
# Author.....: Mitchell Johnston - uid 0
# Contact....: mitch@crn.hopto.org
# Updated....: Mon Apr 20 05:44:38 AM CDT 2026
#----------------------------------

# Sections: Changes variables functions setup main 
# use '#' in vi/vim to jump to word under cursor

# I use this as a front end to my csv cotact list. You can create your own csv or port it from some other format. It has some nice little bash/sed tricks to play with.
#
# Required table pager https://github.com/okbob/pspg
# Required table editor https://hymkor.github.io/csvi

: ' Changes:
Sat Apr 18 2026 Added csvi for edits, pspg for table view
'

# variables
#----------------------------------
[ "$1" == "-D" ] && DEBUG=1 && shift 1     # -D to turn on debug mode
[ "$DEBUG" == 1 ] && echo "---Variables---" && set -x
PS4='$SECONDS $LINENO: '                   # debug prompt
DOW=$(date +%a)                            # day of week: Thu
TODAY=$(date +%m/%d)                       # month/day: 03/25
DOM=$(date +%d)                            # day of month: 25
OS=$(uname -s)                             # OS type: SunOS Linux
NAME=${0##*/}                              # name of the script
DIR="$(basename $PWD)"                     # location started
PDIR="$(cd ..;basename $PWD)"              # parrent dir
DB=~/db/contacts.csv                       # main data store

# Colors - uncomment if needed
R=$(tput setaf 1)                          # red
BR=$(tput setaf 1; tput bold)              # bold red
G=$(tput setaf 2)                          # green
BG=$(tput setaf 2; tput bold)              # bold green
Y=$(tput setaf 3)                          # yellow
BY=$(tput setaf 3; tput bold)              # bold yellow
B=$(tput setaf 4)                          # blue
BM=$(tput setaf 5; tput bold)              # bold magenta
BC=$(tput setaf 6; tput bold)              # bold cyan
C=$(tput setaf 6)                          # cyan
BL=$(tput setaf 7; tput bold)              # bold light grey
BLD=$(tput bold)                           # bold
N=$(tput sgr0)                             # normal
SIT=$(tput sitm)                           # italics
RIT=$(tput ritm)                           # remove italics
UL=$(tput smul)                            # turn underline on
NL=$(tput rmul)                            # turn underline off
RV=$(tput rev)                             # turn on reverse mode
ROWS=$(tput lines)
COLS=$(tput cols)
[ "$DEBUG" == 1 ] && set +x && read -p "${N}-Continue-" -n 1 x

# functions
#----------------------------------

bl(){ ## write a blank line
    # Use: bl
    [ "$DEBUG" == "1" ] && set -x
    echo ""
}

html(){ ## mark up code
    vim -f +"syn on" +"set nonu" +"set foldenable!" +"set nospell" +"run! syntax/2html.vim" +"wq" +"q" $1
}

log(){ ## creates a basic log entry $LOG must be defined
    # Use: log {entry}  
    [ "$DEBUG" == "1" ] && set -x
    logger -i -t "$NAME" "$*"
}

pause(){ ## simple pause routine
    # Use: pause  {optional number of seconds} or "-nt" for no time out 
    [ "$DEBUG" == "1" ] && set -x
    [ "$1" == "-nt" ] && TMOUT="" && shift
    echo "$BY";
    if [ $# -gt 0 ]
    then
        read -t $1 -r -p "${C}Hit any key (${BY}$1${C} second timeout)${N}" -n 1 FOO;
    else
        read -r -p "${C}Hit any key${N}" -n 1 FOO;
    fi;
    bl
}

strip-tags(){ ## remove HTML tags
  # Use: curl https://linuxhint.com/bash_cut_command/ --silent | strip-tags
  sed -e 's/<[^>]*.//g' -
}

xtitle(){ ## set window title
    # Use: xtitle "Text to display"
    printf "\033]0;%s\007" "$*"
}

### CSV Functions ###

add_record(){ ## add an entry to csv file
    local file="$DB"
    local csv_dir=$(dirname "$file")

    # Create directory if it doesn't exist
    mkdir -p "$csv_dir"

    # If file doesn't exist, prompt for headers first
    if [[ ! -f "$file" ]]; then
        echo "File $file not found. Define headers separated by comma (e.g., Name,Age,City):"
        read -r header
        echo "$header" > "$file"
    fi

    # Read the header line
    local header=$(head -n 1 "$file")

    # Use IFS to split the header by comma
    IFS=',' read -ra ADDR <<< "$header"

    local new_record=""

    # Prompt for each header column
    for field in "${ADDR[@]}"; do
        # Remove potential carriage return if file has CRLF line endings
        field=$(echo "$field" | tr -d '\r')
        read -p "Enter $field: " input

        # Escape double quotes and wrap field in quotes
        input="${input//\"/\"\"}"
        new_record+="$input,"
        #new_record+="\"$input\","
    done

    # Remove trailing comma and append to file
    echo "${new_record%,}" >> "$file"
    echo "Record added to $file"
}

check_csv(){ ## basic CSV infromation
    local file="$DB"
    if [[ -f "$file" ]]; then
        echo "--- CSV Stats: $file ---"
        # Total rows (including header)
        echo "Total Rows: $(wc -l < "$file")"
        # Total columns (based on first line)
        echo "Total Columns: $(head -n 1 "$file" | awk -F, '{print NF}')"
        # Header names
        echo "Headers: $(head -n 1 "$file" | sed 's/,/, /g')"
        # File Size
        du -sh "$file"
        echo "--------------------------"
    else
        echo "File not found: $file"
    fi
}

view_record() { ## find and display record
    # Usage: view_csv_record "search_term" "file.csv"
    local search="$1"
    local file="$2"

    # Use awk to filter and print fields vertically
    awk -F, -v s="$search" '
        NR==1 {for (i=1; i<=NF; i++) h[i]=$i; next} # Store header
        {IGNORECASE=1}
        $0 ~ s { # If line matches
            print "--- Record Found ---"
            for (i=1; i<=NF; i++) {
                printf "%-15s: %s\n", h[i], $i
            }
        }
    ' "$file"
}

view_csv() { ## view table
    if [ -z "$1" ]; then
        echo "Usage: view_csv_pretty <file.csv>"
    else
        cat "$1" | column -s, -t | less -F -S -X -K
    fi
}

# setup
#----------------------------------

# this provides a quick way to edit all my scripts on the fly
if [ "$1" == "-E" ]
then
    vim $0
    sed -i -e "7s/.*/# Updated....: $(date)/" $0
    html $0
    cp $0 /var/www/unix
    mv $0.html /var/www/unix
    log "Updated $0"
    exit
fi

# display help if needed
if [ "$1" == "-h" ] || [ "$1" == "--help" ]
then
fmt -s -w $(tput cols) <<END
${BC}$NAME${N} ${SIT}A contact list manager${RIT}

${BY}Options:${N}

-a   # Add entry
-c   # Check csv
-e   # Edit table
-l   # list view
{string} find someone
END
exit
fi

# listing of required apps
command -v bash >/dev/null || sudo apt install bash -qyy
command -v pspg >/dev/null || echo "Required https://github.com/okbob/pspg" 
command -v csvi >/dev/null || echo "Required https://hymkor.github.io/csvi/" 

# directory check
#[[ "$(pwd)" != *"foo"* ]] && echo "$NAME: directory error" && exit 1

# main
#--------------------------- 
[ "$DEBUG" == 1 ] && echo "---Functions---" && typeset -F && read -p "${N}-Continue-" -n 1 x
[ "$DEBUG" == 1 ] && echo "---Main---" && set -x

[ "$#" -eq 0 ] && $0 -h  && exit

case "$1" in
    -a) # add entry
        add_record
        pspg $DB
        ;;
    -c) # check csv
        check_csv
        ;;
    -e) # edit list
        csvi $DB
        ;;
    -l) # list view
        pspg $DB
        ;;
    *) # default lookup and display record
        echo $BC
        view_record "$1" $DB |sed -e "0,/${1}/I s/${1}/${BY}${1^}${BC}/I"
        ;;
esac

exit

# Code snippets
#--------------------------- 

# vim: nospell ft=sh