# include this from .bashrc, .zshrc or
# another shell startup file with:
#   source $HOME/.shellfishrc

# this script does nothing outside ShellFish
if [[ "$LC_TERMINAL" = "ShellFish" ]]; then
  ios_printURIComponent() {
    awk 'BEGIN {while (y++ < 125) z[sprintf("%c", y)] = y
    while (y = substr(ARGV[1], ++j, 1))
    q = y ~ /[a-zA-Z0-9]/ ? q y : q sprintf("%%%02X", z[y])
    printf("%s", q)}' "$1"
  }
  
  ios_printBase64Component() {
    echo -n "$1" | base64
  }
  
  which printf > /dev/null
  ios_hasPrintf=$?
  ios_printf() {
    if [ $ios_hasPrintf ]; then
      printf "$1"
    else
      awk "BEGIN {printf \"$1\"}"
    fi
  }
  
  ios_sequence() {
    if [[ -n "$TMUX" ]]; then
     OUTPUT=$(
      ios_printf '\033Ptmux;\033\033]'
      echo -n "$1" | tr -d '[:space:]'
      ios_printf '\a\033\\' )
    else
     OUTPUT=$(
      ios_printf '\033]'
      echo -n "$1" | tr -d '[:space:]'
      ios_printf '\a' )
    fi
    if [ -t 1 ] ; then
      echo -n $OUTPUT
    elif [[ -n "$SSH_TTY" ]]; then
      echo -n $OUTPUT > $SSH_TTY
    else
      echo >&2 'Standard output is not tty and there is no $SSH_TTY'
    fi
  }
  
  # prepare fifo for communicating result back to shell
  ios_prepareResult() {
    FIFO=$(mktemp)
    rm -f $FIFO
    mkfifo $FIFO
    echo $FIFO
  }
    
  # wait for terminal to complete action
  ios_handleResult() {
    FIFO=$1
    if [ -n "$FIFO" ]; then
      read <$FIFO -s
      rm -f $FIFO
    
      if [[ $REPLY = error* ]]; then
        echo "${REPLY#error=}" | base64 >&2 -d
        return 1
      fi
  
      if [[ $REPLY = result* ]]; then
        echo "${REPLY#result=}" | base64 -d
      fi
    fi
  }

  sharesheet() {
      if [[ $# -eq 0 ]]; then
        if tty -s; then
          cat <<EOF
Usage: sharesheet [FILE]...

Present share sheet for files and directories. Alternatively you can pipe in text and call it without arguments.

If arguments exist inside the Files app changes made are written back to the server.
EOF
        return 0
      fi
    fi

    FIFO=$(ios_prepareResult)
    OUTPUT=$(
      awk 'BEGIN {printf "6;sharesheet://?ver=2&respond="}'
      ios_printBase64Component "$FIFO"
      awk 'BEGIN {printf "&pwd="}'
      ios_printBase64Component "$PWD"
      awk 'BEGIN {printf "&home="}'
      ios_printBase64Component "$HOME"
      for var in "$@"
      do
        awk 'BEGIN {printf "&path="}'
        ios_printBase64Component "$var"
      done
      if [[ $# -eq 0 ]]; then
        text=$(cat -)
        awk 'BEGIN {printf "&text="}'
        ios_printBase64Component "$text"
      fi
     )
    ios_sequence "$OUTPUT"
    ios_handleResult "$FIFO"
  }
  
  quicklook() {
    if [[ $# -eq 0 ]]; then
      if tty -s; then
            cat <<EOF
Usage: quicklook [FILE]...

Show QuickLook preview for files and directories. Alternatively you can pipe in text and call it without arguments.
EOF
        return 0
      fi
    fi
  
    FIFO=$(ios_prepareResult)
    OUTPUT=$(
      awk 'BEGIN {printf "6;quicklook://?ver=2&respond="}'
      ios_printBase64Component "$FIFO"
      awk 'BEGIN {printf "&pwd="}'
      ios_printBase64Component "$PWD"
      awk 'BEGIN {printf "&home="}'
      ios_printBase64Component "$HOME"
      for var in "$@"
      do
        awk 'BEGIN {printf "&path="}'
        ios_printBase64Component "$var"
      done
      if [[ $# -eq 0 ]]; then
        text=$(cat -)
        awk 'BEGIN {printf "&text="}'
        ios_printBase64Component "$text"
      fi
    )
    ios_sequence "$OUTPUT"
    ios_handleResult "$FIFO"
  }

  textastic() {
    if [[ $# -eq 0 ]]; then
      cat <<EOF
Usage: textastic <text-file>

Open in Textastic 9.5 or later.
File must be in directory represented in the Files app to allow writing back edits.
EOF
    else
      if [ ! -e "$1" ]; then
        touch "$1"
      fi
      OUTPUT=$(
        awk 'BEGIN {printf "6;textastic://?ver=2&pwd="}'
        ios_printBase64Component "$PWD"
        awk 'BEGIN {printf "&home="}'
        ios_printBase64Component "$HOME"
        awk 'BEGIN {printf "&path="}'
        ios_printBase64Component "$1"
      )
      ios_sequence "$OUTPUT"
    fi
  }
  
  openUrl() {
    if [[ $# -eq 0 ]]; then
      cat <<EOF
Usage: openUrl <url>

Open URL on iOS.
EOF
    else
      FIFO=$(ios_prepareResult)
      OUTPUT=$(
        awk 'BEGIN {printf "6;open://?ver=2&respond="}'
        ios_printBase64Component "$FIFO"
        awk 'BEGIN {printf "&url="}'
        ios_printBase64Component "$1"
      )
      ios_sequence "$OUTPUT"
      ios_handleResult "$FIFO"
    fi
  }

  runShortcut() {
    local baseUrl="shortcuts://run-shortcut"
    if [[ $1 == "--x-callback" ]]; then
        local baseUrl="shortcuts://x-callback-url/run-shortcut"
        shift
    fi

    if [[ $# -eq 0 ]]; then
      cat <<EOF
Usage: runShortcut [--x-callback] <shortcut-name> [input-for-shortcut]

Run in Shortcuts app bringing back results if --x-callback is included.
EOF
    else
      local name=$(ios_printURIComponent "$1")
      shift
      local input=$(ios_printURIComponent "$*")
      openUrl "$baseUrl?name=$name&input=$input"
    fi
  }

  notify() {
    if [[ $# -eq 0 ]]; then
      cat <<EOF
Usage: notify <title> [body]

Show notification on iOS device.
Title cannot contain semicolon.
EOF
    else
      local title="${1-}" body="${2-}"
      OUTPUT=$(
        echo $title | awk -F";" 'BEGIN {printf "777;notify;"} {printf "%s;", $1}'
        echo $body
      )
      ios_sequence "$OUTPUT"
    fi
  }

  # copy standard input or arguments to iOS clipboard
  pbcopy() {
    OUTPUT=$(
      awk 'BEGIN {printf "52;c;"} '
      if [ $# -eq 0 ]; then
        base64 | tr -d '\n'
      else
        echo -n "$@" | base64 | tr -d '\n'
      fi
    )
    ios_sequence "$OUTPUT"
  }
  
  # paste from iOS device clipboard to standard output
  pbpaste() {
    FIFO=$(ios_prepareResult)
    OUTPUT=$(
      awk 'BEGIN {printf "6;pbpaste://?ver=2&respond="}'
      ios_printBase64Component "$FIFO"
    )
    ios_sequence "$OUTPUT"
    ios_handleResult "$FIFO"
  }

  # Secure ShellFish supports 24-bit colors
  export COLORTERM=truecolor
  
  if [[ -z "$INSIDE_EMACS" && $- = *i* ]]; then
    # tmux mouse mode enables scrolling with
    # swipe and mouse wheel
    if [[ -n "$TMUX" ]]; then
      tmux set -g mouse on
    fi

    # send the current directory using OSC 7 when showing prompt to
    # make filename detection work better for interactive shell
    update_terminal_cwd() {
      ios_sequence $(
        awk "BEGIN {printf \"7;%s\", \"file://$HOSTNAME\"}"
        ios_printURIComponent "$PWD"
      )
    }
    if [ -n "$ZSH_VERSION" ]; then
      precmd() { update_terminal_cwd; }
    elif [[ $PROMPT_COMMAND != *"update_terminal_cwd"* ]]; then
      PROMPT_COMMAND="update_terminal_cwd${PROMPT_COMMAND:+; $PROMPT_COMMAND}"
    fi
  fi
fi