JUMP_LIST=~/.config/z/jump_list

_z_exec() {
  sqlite3 "$JUMP_LIST" "$@"
  return $?
}

function completion/z {
  OPTIONS=( #>#
  "h:; show help text"
  "l:; list aliases"
  "a:; add a new alias"
  "r:; remove alias"
  ) #<#

  command -f completion//parseoptions -n
  if [ -z "$ARGOPT" ] || [ "$ARGOPT" = "r" ]; then
    complete -T $(_z_exec "select alias from jump_list")
  elif [ "$ARGOPT" = "-" ]; then
    command -f completion//completeoptions
  fi
}

! [ -d ~/.config/z ] && mkdir -p ~/.config/z
! [ -f "$JUMP_LIST" ] && _z_exec 'create table jump_list (alias text primary key, directory text not null)'

_z_help() {
  echo 'help:   z -h'
  echo 'goto:   z alias'
  echo 'list:   z -l'
  echo 'add:    z -a alias /path/to/dir'
  echo 'remove: z -r alias'
}

_z_list() {
  _z_exec "select alias || ' -> ' || directory from jump_list order by alias"
}

_z_add() {
  alias=$1
  dir=$2
  if [ -z "$dir" ]; then
    dir=$(pwd)
  fi
  if [ ! -d "$dir" ]; then
    echo "Directory not found: $dir"
    return 1
  fi
  fullpath=$(cd "$dir"; pwd)
  if [ ! -d "$fullpath" ]; then
    echo "Could not change to directory: $fullpath"
    return 1
  else
    alias_esc=$(echo "$alias" | sed "s/'/''/g")
    fullpath_esc=$(echo "$fullpath" | sed "s/'/''/g")
    if ! _z_exec "insert into jump_list values ('$alias_esc', '$fullpath_esc')"; then
      echo "Error adding alias"
      return 1
    fi
  fi
}

_z_remove() {
  alias=$1
  alias_esc=$(echo "$alias" | sed "s/'/''/g")
  rows=$(_z_exec "delete from jump_list where alias='$alias_esc'; select changes()")
  if [ "$rows" -eq 0 ]; then
    echo "Alias not found: $alias"
    return 1
  fi
}

_z_goto() {
  alias=$1
  alias_esc=$(echo "$alias" | sed "s/'/''/g")
  dir=$(_z_exec "select directory from jump_list where alias='$alias_esc'")
  if [ -z "$dir" ]; then
    echo "Alias not found: $alias"
    return 1
  elif [ ! -d "$dir" ]; then
    echo "Directory not found: $dir"
    return 1
  else
    cd "$dir"
  fi
}

z() {
  if [ $# -eq 0 ]; then
    _z_help
    return
  fi
  cmd=$1
  shift
  case $cmd in
  '-h') _z_help;;
  '-l') _z_list;;
  '-a') _z_add "$@";;
  '-r') _z_remove "$@";;
  -*) echo "Unknown command: $cmd"; return 1;;
  *) _z_goto "$cmd";;
  esac
}