#!/usr/bin/env bash
#clear
#export PS4='\e[90m+${LINENO} in ${#BASH_SOURCE[@]}>${FUNCNAME[0]}:${BASH_SOURCE[@]##*/} \e[0m'
#set -x

#echo "starting: $0 <LOG_LEVEL=$1>"

### new.method

# ============================================================================
# otmux - tmux wrapper for oosh
# Makes tmux commands easy to use with intuitive method names
# ============================================================================

# ─────────────────────────────────────────────────────────────────────────────
# SESSION COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.new() # <?name> <?command> # create a new session
{
  if [ -n "$1" ]; then
    local name="$1"
    shift
    tmux new-session -s "$name" "$@"
  else
    tmux new-session "$@"
  fi
}

otmux.attach() # <?session> # attach to a session
{
  if [ -n "$1" ]; then
    tmux attach-session -t "$1"
  else
    tmux attach-session
  fi
}

otmux.a() # <?session> # shorthand for attach
{
  otmux.attach "$@"
}

otmux.detach() # # detach from current session
{
  tmux detach-client "$@"
}

otmux.d() # # shorthand for detach
{
  otmux.detach "$@"
}

otmux.sessions() # # list all sessions
{
  tmux list-sessions "$@"
}

otmux.ls() # # shorthand for sessions
{
  otmux.sessions "$@"
}

otmux.has() # <session> # check if session exists
{
  tmux has-session -t "$1" 2>/dev/null
}

otmux.kill() # <session> # kill a session
{
  if [ -n "$1" ]; then
    tmux kill-session -t "$1"
  else
    error.log "usage: otmux kill <session-name>"
    return 1
  fi
}

otmux.killAll() # # kill all sessions except current
{
  tmux kill-session -a "$@"
}

otmux.rename() # <new-name> # rename current session
{
  if [ -n "$1" ]; then
    tmux rename-session "$1"
  else
    error.log "usage: otmux rename <new-name>"
    return 1
  fi
}

otmux.switch() # <session> # switch to another session
{
  if [ -n "$1" ]; then
    tmux switch-client -t "$1"
  else
    tmux switch-client "$@"
  fi
}

otmux.last() # # switch to last session
{
  tmux switch-client -l
}

otmux.next() # # switch to next session
{
  tmux switch-client -n
}

otmux.prev() # # switch to previous session
{
  tmux switch-client -p
}

otmux.lock() # # lock the current session
{
  tmux lock-session "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# WINDOW COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.newWindow() # <?name> <?command> # create a new window
{
  if [ -n "$1" ]; then
    tmux new-window -n "$1" "${@:2}"
  else
    tmux new-window "$@"
  fi
}

otmux.nw() # <?name> <?command> # shorthand for newWindow
{
  otmux.newWindow "$@"
}

otmux.windows() # # list windows in current session
{
  tmux list-windows "$@"
}

otmux.lsw() # # shorthand for windows
{
  otmux.windows "$@"
}

otmux.selectWindow() # <window> # select a window by index or name
{
  if [ -n "$1" ]; then
    tmux select-window -t "$1"
  else
    error.log "usage: otmux selectWindow <window>"
    return 1
  fi
}

otmux.sw() # <window> # shorthand for selectWindow
{
  otmux.selectWindow "$@"
}

otmux.nextWindow() # # go to next window
{
  tmux next-window
}

otmux.prevWindow() # # go to previous window
{
  tmux previous-window
}

otmux.lastWindow() # # go to last window
{
  tmux last-window
}

otmux.killWindow() # <?window> # kill a window
{
  if [ -n "$1" ]; then
    tmux kill-window -t "$1"
  else
    tmux kill-window
  fi
}

otmux.kw() # <?window> # shorthand for killWindow
{
  otmux.killWindow "$@"
}

otmux.renameWindow() # <new-name> # rename current window
{
  if [ -n "$1" ]; then
    tmux rename-window "$1"
  else
    error.log "usage: otmux renameWindow <new-name>"
    return 1
  fi
}

otmux.rw() # <new-name> # shorthand for renameWindow
{
  otmux.renameWindow "$@"
}

otmux.moveWindow() # <target> # move window to target
{
  tmux move-window "$@"
}

otmux.swapWindow() # <target> # swap window with target
{
  tmux swap-window "$@"
}

otmux.linkWindow() # <src> <dst> # link window from src to dst
{
  tmux link-window "$@"
}

otmux.unlinkWindow() # <?window> # unlink a window
{
  tmux unlink-window "$@"
}

otmux.findWindow() # <pattern> # find window by pattern
{
  if [ -n "$1" ]; then
    tmux find-window "$1"
  else
    error.log "usage: otmux findWindow <pattern>"
    return 1
  fi
}

otmux.rotateWindow() # # rotate panes in window
{
  tmux rotate-window "$@"
}

otmux.respawnWindow() # <?command> # respawn window with command
{
  tmux respawn-window "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# PANE COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.split() # <?command> # split pane horizontally
{
  tmux split-window "$@"
}

otmux.splitH() # <?command> # split pane horizontally (alias)
{
  tmux split-window -h "$@"
}

otmux.splitV() # <?command> # split pane vertically
{
  tmux split-window -v "$@"
}

otmux.panes() # # list panes in current window
{
  tmux list-panes "$@"
}

otmux.lsp() # # shorthand for panes
{
  otmux.panes "$@"
}

otmux.selectPane() # <direction> # select pane (U/D/L/R or index)
{
  case "$1" in
    U|u|up)    tmux select-pane -U ;;
    D|d|down)  tmux select-pane -D ;;
    L|l|left)  tmux select-pane -L ;;
    R|r|right) tmux select-pane -R ;;
    *)         tmux select-pane -t "$1" ;;
  esac
}

otmux.sp() # <direction> # shorthand for selectPane
{
  otmux.selectPane "$@"
}

otmux.up() # # select pane above
{
  tmux select-pane -U
}

otmux.down() # # select pane below
{
  tmux select-pane -D
}

otmux.left() # # select pane to the left
{
  tmux select-pane -L
}

otmux.right() # # select pane to the right
{
  tmux select-pane -R
}

otmux.lastPane() # # select last pane
{
  tmux last-pane
}

otmux.killPane() # <?pane> # kill a pane
{
  if [ -n "$1" ]; then
    tmux kill-pane -t "$1"
  else
    tmux kill-pane
  fi
}

otmux.kp() # <?pane> # shorthand for killPane
{
  otmux.killPane "$@"
}

otmux.breakPane() # # break pane into a new window
{
  tmux break-pane "$@"
}

otmux.joinPane() # <target> # join pane to target window
{
  tmux join-pane "$@"
}

otmux.swapPane() # <target> # swap pane with target
{
  tmux swap-pane "$@"
}

otmux.movePane() # <target> # move pane to target
{
  tmux move-pane "$@"
}

otmux.resizePane() # <direction> <?amount> # resize pane (U/D/L/R)
{
  local amount="${2:-5}"
  case "$1" in
    U|u|up)    tmux resize-pane -U "$amount" ;;
    D|d|down)  tmux resize-pane -D "$amount" ;;
    L|l|left)  tmux resize-pane -L "$amount" ;;
    R|r|right) tmux resize-pane -R "$amount" ;;
    *)         tmux resize-pane "$@" ;;
  esac
}

otmux.rp() # <direction> <?amount> # shorthand for resizePane
{
  otmux.resizePane "$@"
}

otmux.zoom() # # toggle pane zoom
{
  tmux resize-pane -Z
}

otmux.z() # # shorthand for zoom
{
  otmux.zoom
}

otmux.respawnPane() # <?command> # respawn pane with command
{
  tmux respawn-pane "$@"
}

otmux.pipePane() # <?command> # pipe pane output to command
{
  tmux pipe-pane "$@"
}

otmux.displayPanes() # # display pane numbers
{
  tmux display-panes "$@"
}

otmux.dp() # # shorthand for displayPanes
{
  otmux.displayPanes "$@"
}

otmux.capturePane() # <?options> # capture pane contents
{
  tmux capture-pane "$@"
}

otmux.clearHistory() # # clear pane history
{
  tmux clear-history "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# LAYOUT COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.layout() # <layout> # set window layout
{
  if [ -n "$1" ]; then
    tmux select-layout "$1"
  else
    tmux select-layout
  fi
}
otmux.layout.completion.layout() {
  echo "even-horizontal"
  echo "even-vertical"
  echo "main-horizontal"
  echo "main-vertical"
  echo "tiled"
}

otmux.evenH() # # set even-horizontal layout
{
  tmux select-layout even-horizontal
}

otmux.evenV() # # set even-vertical layout
{
  tmux select-layout even-vertical
}

otmux.mainH() # # set main-horizontal layout
{
  tmux select-layout main-horizontal
}

otmux.mainV() # # set main-vertical layout
{
  tmux select-layout main-vertical
}

otmux.tiled() # # set tiled layout
{
  tmux select-layout tiled
}

otmux.nextLayout() # # cycle to next layout
{
  tmux next-layout
}

otmux.prevLayout() # # cycle to previous layout
{
  tmux previous-layout
}

# ─────────────────────────────────────────────────────────────────────────────
# BUFFER COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.buffers() # # list buffers
{
  tmux list-buffers "$@"
}

otmux.lsb() # # shorthand for buffers
{
  otmux.buffers "$@"
}

otmux.showBuffer() # <?buffer> # show buffer contents
{
  tmux show-buffer "$@"
}

otmux.setBuffer() # <data> # set buffer data
{
  if [ -n "$1" ]; then
    tmux set-buffer "$1"
  else
    error.log "usage: otmux setBuffer <data>"
    return 1
  fi
}

otmux.loadBuffer() # <file> # load buffer from file
{
  if [ -n "$1" ]; then
    tmux load-buffer "$1"
  else
    error.log "usage: otmux loadBuffer <file>"
    return 1
  fi
}

otmux.saveBuffer() # <file> # save buffer to file
{
  if [ -n "$1" ]; then
    tmux save-buffer "$1"
  else
    error.log "usage: otmux saveBuffer <file>"
    return 1
  fi
}

otmux.deleteBuffer() # <?buffer> # delete a buffer
{
  tmux delete-buffer "$@"
}

otmux.pasteBuffer() # # paste buffer contents
{
  tmux paste-buffer "$@"
}

otmux.paste() # # shorthand for pasteBuffer
{
  otmux.pasteBuffer "$@"
}

otmux.chooseBuffer() # # interactively choose a buffer
{
  tmux choose-buffer "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# CLIENT COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.clients() # # list clients
{
  tmux list-clients "$@"
}

otmux.lsc() # # shorthand for clients
{
  otmux.clients "$@"
}

otmux.detachClient() # <?client> # detach a client
{
  tmux detach-client "$@"
}

otmux.suspendClient() # # suspend current client
{
  tmux suspend-client "$@"
}

otmux.refreshClient() # # refresh client display
{
  tmux refresh-client "$@"
}

otmux.chooseClient() # # interactively choose a client
{
  tmux choose-client "$@"
}

otmux.chooseTree() # # interactively choose session/window
{
  tmux choose-tree "$@"
}

otmux.lockClient() # # lock the client
{
  tmux lock-client "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# SERVER COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.startServer() # # start the tmux server
{
  tmux start-server
}

otmux.killServer() # # kill the tmux server
{
  tmux kill-server
}

otmux.lockServer() # # lock all clients
{
  tmux lock-server
}

otmux.info() # # show server information
{
  tmux info
}

# ─────────────────────────────────────────────────────────────────────────────
# CONFIGURATION COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.source() # <file> # source a config file
{
  if [ -n "$1" ]; then
    tmux source-file "$1"
  else
    tmux source-file ~/.tmux.conf
  fi
}

otmux.set() # <option> <value> # set a tmux option
{
  tmux set-option "$@"
}

otmux.setGlobal() # <option> <value> # set a global option
{
  tmux set-option -g "$@"
}

otmux.setWindow() # <option> <value> # set a window option
{
  tmux set-window-option "$@"
}

otmux.show() # <?option> # show options
{
  tmux show-options "$@"
}

otmux.showGlobal() # <?option> # show global options
{
  tmux show-options -g "$@"
}

otmux.showWindow() # <?option> # show window options
{
  tmux show-window-options "$@"
}

otmux.showHooks() # # show hooks
{
  tmux show-hooks "$@"
}

otmux.setHook() # <hook> <command> # set a hook
{
  tmux set-hook "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# KEY BINDING COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.bind() # <key> <command> # bind a key
{
  tmux bind-key "$@"
}

otmux.unbind() # <key> # unbind a key
{
  tmux unbind-key "$@"
}

otmux.keys() # # list key bindings
{
  tmux list-keys "$@"
}

otmux.lsk() # # shorthand for keys
{
  otmux.keys "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# ENVIRONMENT COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.setEnv() # <name> <value> # set environment variable
{
  tmux set-environment "$@"
}

otmux.showEnv() # <?name> # show environment variables
{
  tmux show-environment "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# SEND/RUN COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.send() # <keys> # send keys to pane
{
  tmux send-keys "$@"
}

otmux.sendEnter() # <text> # send text followed by Enter
{
  tmux send-keys "$@" Enter
}

otmux.run() # <command> # run shell command
{
  tmux run-shell "$@"
}

otmux.display() # <message> # display a message
{
  tmux display-message "$@"
}

otmux.msg() # <message> # shorthand for display
{
  otmux.display "$@"
}

otmux.confirm() # <command> # confirm before running command
{
  tmux confirm-before "$@"
}

otmux.prompt() # <?template> # command prompt
{
  tmux command-prompt "$@"
}

otmux.menu() # # display menu
{
  tmux display-menu "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# COPY MODE COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.copy() # # enter copy mode
{
  tmux copy-mode "$@"
}

otmux.clock() # # show clock
{
  tmux clock-mode "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# UTILITY COMMANDS
# ─────────────────────────────────────────────────────────────────────────────

otmux.wait() # <channel> # wait for a channel
{
  tmux wait-for "$@"
}

otmux.if() # <condition> <cmd1> <?cmd2> # conditional execution
{
  tmux if-shell "$@"
}

otmux.showMessages() # # show server messages
{
  tmux show-messages "$@"
}

otmux.commands() # # list all tmux commands
{
  tmux list-commands "$@"
}

otmux.lscm() # # shorthand for commands
{
  otmux.commands "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# GLOBAL FLAGS
# ─────────────────────────────────────────────────────────────────────────────

otmux.256color() # <command> # force 256 color mode
{
  tmux -2 "$@"
}

otmux.control() # <?command> # start in control mode
{
  tmux -C "$@"
}

otmux.utf8() # <command> # force UTF-8 mode
{
  tmux -u "$@"
}

otmux.verbose() # <command> # enable verbose logging
{
  tmux -v "$@"
}

otmux.socket() # <name> <command> # use specific socket name
{
  local name="$1"
  shift
  tmux -L "$name" "$@"
}

otmux.socketPath() # <path> <command> # use specific socket path
{
  local path="$1"
  shift
  tmux -S "$path" "$@"
}

otmux.config() # <file> <command> # use specific config file
{
  local file="$1"
  shift
  tmux -f "$file" "$@"
}

# ─────────────────────────────────────────────────────────────────────────────
# STATUS & HELP
# ─────────────────────────────────────────────────────────────────────────────

otmux.version() # # show tmux version
{
  tmux -V
}

otmux.v() # # shorthand for version
{
  otmux.version
}

otmux.help() # # show tmux help
{
  tmux --help 2>&1 | head -50
  echo ""
  echo "For full documentation: man tmux"
}

otmux.status() # # show current tmux status
{
  if [ -n "$TMUX" ]; then
    echo "Inside tmux session"
    tmux display-message -p "Session: #S | Window: #I:#W | Pane: #P"
    echo ""
    echo "Sessions:"
    tmux list-sessions
  else
    echo "Not inside a tmux session"
    if tmux list-sessions 2>/dev/null; then
      echo ""
      echo "Available sessions above. Use 'otmux attach' to connect."
    else
      echo "No tmux server running. Use 'otmux new' to start."
    fi
  fi
  echo ""
  echo "otmux - tmux wrapper for oosh"
  echo "Type 'otmux help' for all options"
}

# ─────────────────────────────────────────────────────────────────────────────
# USAGE
# ─────────────────────────────────────────────────────────────────────────────

otmux.usage()
{
  local this=${0##*/}
  echo "You started"
  echo "$0

  otmux - tmux wrapper for oosh
  Makes tmux commands easy to remember!

  Usage:
  $this command     Description
  ─────────────────────────────────────────────────────
  SESSIONS:
      new <name>      create new session
      attach <sess>   attach to session (a)
      detach          detach from session (d)
      sessions        list sessions (ls)
      kill <sess>     kill a session
      rename <name>   rename session
      switch <sess>   switch to session
      last/next/prev  navigate sessions

  WINDOWS:
      newWindow <n>   create window (nw)
      windows         list windows (lsw)
      selectWindow    select window (sw)
      killWindow      kill window (kw)
      renameWindow    rename window (rw)
      nextWindow      next window
      prevWindow      previous window
      findWindow      find by pattern

  PANES:
      split           split horizontally
      splitH/splitV   split h/v explicitly
      panes           list panes (lsp)
      selectPane      select pane (sp)
      up/down/l/r     navigate panes
      killPane        kill pane (kp)
      zoom            toggle zoom (z)
      resizePane      resize pane (rp)
      breakPane       break to window
      joinPane        join to window
      displayPanes    show pane numbers (dp)

  LAYOUTS:
      layout <type>   set layout
      evenH/evenV     even layouts
      mainH/mainV     main layouts
      tiled           tiled layout
      nextLayout      cycle layouts

  BUFFERS:
      buffers         list buffers (lsb)
      paste           paste buffer
      chooseBuffer    choose buffer
      saveBuffer      save to file
      loadBuffer      load from file

  CONFIG:
      source <file>   source config
      set/setGlobal   set options
      show/showGlobal show options
      bind/unbind     key bindings
      keys            list bindings (lsk)

  UTILITY:
      send <keys>     send keys to pane
      run <cmd>       run shell command
      display <msg>   show message
      copy            enter copy mode
      clock           show clock
      status          show status
      v               show version
  ─────────────────────────────────────────────────────

  Examples:
    $this new dev                 # new session 'dev'
    $this splitH                  # split horizontally
    $this send 'ls -la' Enter     # send command
    $this zoom                    # toggle pane zoom
    $this layout tiled            # tiled layout
    $this attach dev              # attach to 'dev'
  "
}

otmux.start()
{
  #echo "sourcing init"
  source this

  if [ -z "$1" ]; then
    otmux.status
    return 0
  fi

  this.start "$@"
}

otmux.start "$@"
