#
# Layout Helpers
#
# These functions are available exclusively within layout files, and enable
# the layout files to function at all, but also provide useful short-hands to
# otherwise more complex means.
#

# Alias tmux to tmuxifier-tmux wrapper.
tmux() {
  tmuxifier-tmux "$@"
}

# Create a new window.
#
# Arguments:
#   - $1: (optional) Name/title of window.
#   - $2: (optional) Shell command to execute when window is created.
#
new_window() {
  if [ -n "$1" ]; then local winarg=(-n "$1"); fi
  if [ -n "$2" ]; then local command=("$2"); fi

  tmuxifier-tmux new-window -t "$session:" "${winarg[@]}" "${command[@]}"

  # Disable renaming if a window name was given.
  if [ -n "$1" ]; then tmuxifier-tmux set-option -t "$1" allow-rename off; fi

  window="$(__get_current_window_index)"
  __go_to_window_or_session_path
}

# Split current window/pane vertically.
#
# Arguments:
#   - $1: (optional) Percentage of frame the new pane will use.
#   - $2: (optional) Target pane ID to split in current window.
#
split_v() {
  if [ "$(tmuxifier-tmux-version "3.0")" == ">" ]; then
    # Tmux 3.1 and later.
    if [ -n "$1" ]; then local percentage=(-l "$1"'%'); fi
  else
    if [ -n "$1" ]; then local percentage=(-p "$1"); fi
  fi
  tmuxifier-tmux split-window -t "$session:$window.$2" -v "${percentage[@]}"
  __go_to_window_or_session_path
}

# Split current window/pane horizontally.
#
# Arguments:
#   - $1: (optional) Percentage of frame the new pane will use.
#   - $2: (optional) Target pane ID to split in current window.
#
split_h() {
  if [ "$(tmuxifier-tmux-version "3.0")" == ">" ]; then
    # Tmux 3.1 and later.
    if [ -n "$1" ]; then local percentage=(-l "$1"'%'); fi
  else
    if [ -n "$1" ]; then local percentage=(-p "$1"); fi
  fi
  tmuxifier-tmux split-window -t "$session:$window.$2" -h "${percentage[@]}"
  __go_to_window_or_session_path
}

# Split current window/pane vertically by line count.
#
# Arguments:
#   - $1: (optional) Number of lines the new pane will use.
#   - $2: (optional) Target pane ID to split in current window.
#
split_vl() {
  if [ -n "$1" ]; then local count=(-l "$1"); fi
  tmuxifier-tmux split-window -t "$session:$window.$2" -v "${count[@]}"
  __go_to_window_or_session_path
}

# Split current window/pane horizontally by column count.
#
# Arguments:
#   - $1: (optional) Number of columns the new pane will use.
#   - $2: (optional) Target pane ID to split in current window.
#
split_hl() {
  if [ -n "$1" ]; then local count=(-l "$1"); fi
  tmuxifier-tmux split-window -t "$session:$window.$2" -h "${count[@]}"
  __go_to_window_or_session_path
}

# Run clock mode.
#
# Arguments:
#   - $1: (optional) Target pane ID in which to run
clock() {
  tmuxifier-tmux clock-mode -t "$session:$window.$1"
}

# Select a specific window.
#
# Arguments:
#   - $1: Window ID or name to select.
#
select_window() {
  tmuxifier-tmux select-window -t "$session:$1"
  window="$(__get_current_window_index)"
}

# Select a specific pane in the current window.
#
# Arguments:
#   - $1: Pane ID to select.
#
select_pane() {
  tmuxifier-tmux select-pane -t "$session:$window.$1"
}

# Balance windows vertically with the "even-vertical" layout.
#
# Arguments:
#   - $1: (optional) Window ID or name to operate on.
#
balance_windows_vertical() {
  tmuxifier-tmux select-layout -t "$session:${1:-$window}" even-vertical
}

# Balance windows horizontally with the "even-horizontal" layout.
#
# Arguments:
#   - $1: (optional) Window ID or name to operate on.
#
balance_windows_horizontal() {
  tmuxifier-tmux select-layout -t "$session:${1:-$window}" even-horizontal
}

# Turn on synchronize-panes in a window.
#
# Arguments:
#   - $1: (optional) Window ID or name to operate on.
#
synchronize_on() {
  tmuxifier-tmux set-window-option -t "$session:${1:-$window}" \
                 synchronize-panes on
}

# Turn off synchronize-panes in a window.
#
# Arguments:
#   - $1: (optional) Window ID or name to operate on.
#
synchronize_off() {
  tmuxifier-tmux set-window-option -t "$session:${1:-$window}" \
                 synchronize-panes off
}

# Send/paste keys to the currently active pane/window.
#
# Arguments:
#   - $1: String to paste.
#   - $2: (optional) Target pane ID to send input to.
#
send_keys() {
  tmuxifier-tmux send-keys -t "$session:$window.$2" "$1"
}

# Runs a shell command in the currently active pane/window.
#
# Arguments:
#   - $1: Shell command to run.
#   - $2: (optional) Target pane ID to run command in.
#
run_cmd() {
  send_keys "$1" "$2"
  send_keys "C-m" "$2"
}

# Customize session root path. Default is `$HOME`.
#
# Arguments:
#   - $1: Directory path to use for session root.
#
session_root() {
  local dir="$(__expand_path $@)"
  if [ -d "$dir" ]; then
    session_root="$dir"
  fi
}

# Customize window root path. Default is `$session_root`.
#
# Arguments:
#   - $1: Directory path to use for window root.
#
window_root() {
  local dir="$(__expand_path $@)"
  if [ -d "$dir" ]; then
    window_root="$dir"
  fi
}

# Load specified window layout.
#
# Arguments:
#   - $1: Name of or file path to window layout to load.
#   - $2: (optional) Override default window name.
#
load_window() {
  local file="$1"
  if [ ! -f "$file" ]; then
    file="$TMUXIFIER_LAYOUT_PATH/$1.window.sh"
  fi

  if [ -f "$file" ]; then
    if [ $# -gt 1 ]; then
      window="$2"
    else
      window="${1/%.window.sh}"
      window="${window/%.sh}"
    fi
    source "$file"
    window=

    # Reset `$window_root`.
    if [[ "$window_root" != "$session_root" ]]; then
      window_root "$session_root"
    fi
  else
    echo "\"$1\" window layout not found." >&2
    return 1
  fi
}

# Load specified session layout.
#
# Arguments:
#   - $1: Name of or file path to session layout to load.
#   - $2: (optional) Override default window name.
#
load_session() {
  local file
  if [ "${1#*/}" = "$1" ]; then
    # There's no slash in the path.
    if [ -f "$TMUXIFIER_LAYOUT_PATH/$1.session.sh" ] || [ ! -f "$1" ]; then
      file="$TMUXIFIER_LAYOUT_PATH/$1.session.sh"
    else
      # bash's 'source' requires an slash in the filename to not use $PATH.
      file="./$1"
    fi
  else
    file="$1"
  fi

  if ! [ -f "$file" ]; then
    echo "\"$1\" session layout not found." >&2
    return 1
  fi

  if [ $# -gt 1 ]; then
    session="$2"
  else
    session="${1/%.session.sh}"
    session="${session/%.sh}"
  fi

  set_default_path=true
  source "$file"
  session=

  # Reset `$session_root`.
  if [[ "$session_root" != "$HOME" ]]; then
    session_root="$HOME"
  fi
}

# Create a new session, returning 0 on success, 1 on failure.
#
# Arguments:
#   - $1: (optional) Name of session to create, if not specified `$session`
#         is used.
#
# Example usage:
#
#   if initialize_session; then
#     load_window "example"
#   fi
#
initialize_session() {
  if [ -n "$1" ]; then
    session="$1"
  fi

  # Ensure tmux server is running for has-session check.
  tmuxifier-tmux start-server

  # Check if the named session already exists.
  if tmuxifier-tmux list-sessions | grep -q "^$session:"; then
    return 1
  fi

  # Tmux 1.8 and earlier.
  if [ "$(tmuxifier-tmux-version "1.9")" == "<" ]; then
    # Create the new session.
    env TMUX="" tmuxifier-tmux new-session -d -s "$session"

    # Set default-path for session
    if [ -n "$session_root" ] && [ -d "$session_root" ]; then
      cd "$session_root"

      $set_default_path && tmuxifier-tmux \
        set-option -t "$session:" \
        default-path "$session_root" 1>/dev/null
    fi

  # Tmux 1.9 and later.
  else
    if $set_default_path; then
      local session_args=(-c "$session_root")
    fi

    env TMUX="" tmuxifier-tmux new-session \
      -d -s "$session" "${session_args[@]}"
  fi

  if $set_default_path && [[ "$session_root" != "$HOME" ]]; then
    tmuxifier-tmux setenv -t "$session:" \
      TMUXIFIER_SESSION_ROOT "$session_root"
  fi

  # In order to ensure only specified windows are created, we move the
  # default window to position 999, and later remove it with the
  # `finalize_and_go_to_session` function.
  local first_window_index=$(__get_first_window_index)
  tmuxifier-tmux move-window \
    -s "$session:$first_window_index" -t "$session:999"
}

# Finalize session creation and then switch to it if needed.
#
# When the session is created, it leaves a unused window in position #999,
# this is the default window which was created with the session, but it's also
# a window that was not explicitly created. Hence we kill it.
#
# If the session was created, we've already been switched to it. If it was not
# created, but already existed, then we'll need to specifically switch to it.
#
finalize_and_go_to_session() {
  ! tmuxifier-tmux kill-window -t "$session:999" 2>/dev/null
  if [[ "$(tmuxifier-current-session)" != "$session" ]]; then
    __go_to_session
  fi
}


#
# Internal functions
#

# Expands given path.
#
# Example:
#
#   $ __expand_path "~/Projects"
#   /Users/jimeh/Projects
#
__expand_path() {
  echo $(eval echo "$@")
}

__get_first_window_index() {
  local index=$(tmuxifier-tmux list-windows -t "$session:" \
    -F "#{window_index}" 2>/dev/null)

  if [ -n "$index" ]; then
    echo "$index" | head -1
  else
    echo "0"
  fi
}

__get_current_window_index() {
  local lookup=$(tmuxifier-tmux list-windows -t "$session:" \
    -F "#{window_active}:#{window_index}" 2>/dev/null | grep "^1:")

  if [ -n "$lookup" ]; then
    echo "${lookup/1:}"
  fi
}

__go_to_session() {
  if [ -z "$TMUX" ]; then
    tmuxifier-tmux $TMUXIFIER_TMUX_ITERM_ATTACH -u \
      attach-session -t "$session:"
  else
    tmuxifier-tmux -u switch-client -t "$session:"
  fi
}

__go_to_window_or_session_path() {
  local target_path

  if [ -n "$window_root" ]; then
    target_path="$window_root"
  elif [ -n "$TMUXIFIER_SESSION_ROOT" ]; then
    target_path="$TMUXIFIER_SESSION_ROOT"
  elif [ -n "$session_root" ]; then
    target_path="$session_root"
  fi

  # local window_or_session_root=${window_root-$session_root}
  if [ -n "$target_path" ]; then
    run_cmd " cd \"$target_path\""
    run_cmd " clear"
  fi
}
