#!/usr/bin/env bash

# Prevent the utils from being included multiple times.
[ -n "$IMPROMPTU_UTILS_LOADED" ] && return
IMPROMPTU_UTILS_LOADED="true"

impromptu_ensure_constants() {
  if [[ -z "$IMPROMPTU_PORT" ]]; then
    IMPROMPTU_PORT="1624"
  fi
}

# Checks if Impromptu was sourced into an interactive shell.
impromptu_in_interactive_shell() {
  [[ $- == *i* ]]
}

# Pings the Impromptu socket server.
impromptu_ping_server() {
  # The suffix of the PID file is either the basename of the socket (with extension)
  # or the port of the Impromptu server.
  if [[ -n "$IMPROMPTU_UNIX_DOMAIN_SOCKET" ]]; then
    suffix="${IMPROMPTU_UNIX_DOMAIN_SOCKET##*/}"
  else
    suffix="$IMPROMPTU_PORT"
  fi

  pid_file="$IMPROMPTU_DIR/tmp/server-$suffix.pid"
  # Checks if the pid file exists and checks if the process is still running.
  [ -f $pid_file ] && kill -0 $(cat $pid_file) 2> /dev/null
}

# Ensures an Impromptu socket server is running.
impromptu_ensure_server() {
  impromptu_ping_server
  if [[ "$?" -eq 0 ]]; then
    return 0
  fi

  # A server isn't running; try to start one.
  # Ensure the `tmp` directory exists.
  tmp_dir="$IMPROMPTU_DIR/tmp"
  [ -d $tmp_dir ] || mkdir $tmp_dir

  # Check if we're using a Unix domain socket or a port.
  if [[ -n "$IMPROMPTU_UNIX_DOMAIN_SOCKET" ]]; then
    # Check if the socket already exists.
    if [[ -S $IMPROMPTU_UNIX_DOMAIN_SOCKET ]]; then
      # Overwrite the socket.
      rm "$IMPROMPTU_UNIX_DOMAIN_SOCKET" &> /dev/null

    # Check if the path to the socket is a different file.
    elif [[ -e $IMPROMPTU_UNIX_DOMAIN_SOCKET ]]; then
      echo "A file exists at the location of the Impromptu Unix domain socket."
      echo "Please specify a different path."
      return 1
    fi
  fi

  # Start the server process in the foreground.
  if [[ -n "$_impromptu_start_in_foreground" ]]; then
    "$IMPROMPTU_INTERNAL_BIN/server" --port "$IMPROMPTU_PORT" --path "$IMPROMPTU_UNIX_DOMAIN_SOCKET" "$@"

  # Start the server as a daemon in a subshell.
  else
    (
      # Ensure the server is detached from this process.
      nohup "$IMPROMPTU_INTERNAL_BIN/server" --port "$IMPROMPTU_PORT" --path "$IMPROMPTU_UNIX_DOMAIN_SOCKET" >& /dev/null "$@" &
    )

    echo "Starting Impromptu server..."
    sleep 1

    impromptu_ping_server
    if [ "$?" -eq 0 ]; then
      return 0
    else
      # The port/socket may already be in use.
      echo "Could not start Impromptu server."
      return 1
    fi
  fi
}

# Opens a connection to the Impromptu socket server.
# Defaults to a timeout of 1 second.
impromptu_server_connection() {
  if [[ -n "$1" ]]; then
    timeout="$1"
  else
    timeout="1"
  fi

  if [[ -n "$IMPROMPTU_UNIX_DOMAIN_SOCKET" ]]; then
    nc -w "$timeout" -U "$IMPROMPTU_UNIX_DOMAIN_SOCKET"
  else
    nc -w "$timeout" localhost "$IMPROMPTU_PORT"
  fi
}

# Prints the impromptu environment (including relevant local variables).
impromptu_env() {
  # Record the shell's environment.
  request_env="$(printenv)
IMPROMPTU_LAST_EXIT_CODE=$IMPROMPTU_LAST_EXIT_CODE
IMPROMPTU_JOBS_COUNT=$(jobs|wc -l|sed 's/ //g')"

  # Set the current shell.
  if [ -n "$1" ]; then
    request_env+="
IMPROMPTU_SHELL=$1"
  fi

  echo -n "$request_env"
}

# The method used for bash's "PROMPT_COMMAND" and zsh's "precmd".
# All arguments are passed on to `impromptu print`.
impromptu_prompt_command () {
  # Record the last exit code before any methods are executed.
  export IMPROMPTU_LAST_EXIT_CODE=$?

  # `update_terminal_cwd` is an OS X specific command that ensures Terminal.app
  # maintains the correct directory when a new tab is opened (if that setting is
  # enabled). This is usually bound to `$PROMPT_COMMAND`, but is overwritten when
  # we rebind `$PROMPT_COMMAND`. We need to run `update_terminal_cwd` first, or
  # else it will interfere with the cursoring in bash.
  command -v update_terminal_cwd >/dev/null 2>&1 && update_terminal_cwd

  export PS1="$(impromptu print $@)"
}
