#!/usr/bin/env bash

### ARCHIVE EXTRACTION
# usage: ex <file>
function ex {
  if [ -z "$1" ]; then
    # display usage if no parameters given
    echo "Usage: ex <path/file_name>.<zip|rar|bz2|gz|tar|tbz2|tgz|Z|7z|xz|ex|tar.bz2|tar.gz|tar.xz>"
    echo "       extract <path/file_name_1.ext> [path/file_name_2.ext] [path/file_name_3.ext]"
  else
    for n in "$@"; do
      if [ -f "$n" ]; then
        case "${n%,}" in
        *.cbt | *.tar.bz2 | *.tar.gz | *.tar.xz | *.tbz2 | *.tgz | *.txz | *.tar)
          tar xvf "$n"
          ;;
        *.lzma) unlzma ./"$n" ;;
        *.bz2) bunzip2 ./"$n" ;;
        *.cbr | *.rar) unrar x -ad ./"$n" ;;
        *.gz) gunzip ./"$n" ;;
        *.cbz | *.epub | *.zip) unzip ./"$n" ;;
        *.z) uncompress ./"$n" ;;
        *.7z | *.arj | *.cab | *.cb7 | *.chm | *.deb | *.dmg | *.iso | *.lzh | *.msi | *.pkg | *.rpm | *.udf | *.wim | *.xar)
          7z x ./"$n"
          ;;
        *.xz) unxz ./"$n" ;;
        *.exe) cabextract ./"$n" ;;
        *.cpio) cpio -id <./"$n" ;;
        *.cba | *.ace) unace x ./"$n" ;;
        *)
          echo "ex: '$n' - unknown archive method"
          return 1
          ;;
        esac
      else
        echo "'$n' - file does not exist"
        return 1
      fi
    done
  fi
}

function ensure {
  if [ -z "$1" ]; then
    echo "Usage: ensure <command>"
  else
    if ! command -v $1 &>/dev/null; then
      echo "$1 could not be found"
    fi
  fi
}

# Functions for quick base conversion in the terminal

function htd {
  echo "$((0x$1))"
}

function b2d {
  echo "obase=10; ibase=2; $1" | bc
}

function h2d {
  echo "obase=10; ibase=16; $1" | bc
}

function b2h {
  echo "obase=16; ibase=2; $1" | bc
}

function h2b {
  echo "obase=2; ibase=16; $1" | bc
}

function d2h {
  echo "obase=16; ibase=10; $1" | bc
}

function d2b {
  echo "obase=2; ibase=10; $1" | bc
}

#The following functions provide utility for finding a file in a certain directory tree, and then cd'ing to the parent directory containing that file

# File $(search begins in users home directory
gotoh() {
  cd -- "$(dirname "$(fd $1 $HOME | fzy)")"
}

# Search begins in /etc
gotoe() {

  cd -- "$(dirname "$(fd $1 /etc | fzy)")"

}

# global search, but not in runtime and root dirs
#
goto() {

  cd -- "$(dirname "$(fd $1 $HOME /bin /usr/local /usr /etc | fzy)")"

}

# Easier cd'ing (aliases here because they depend on dots() function being available)
# Alias for one level up
#alias ..="command cd .."

dots() {
  # Extract the input argument
  local input="$1"

  # Ensure input consists only of dots
  if [[ ! $input =~ ^\.+$ ]]; then
    echo "Error: 'dots' function accepts only dots (.., ..., ...., etc.)"
    return 1
  fi

  # Count the number of dots in the input
  local depth=${#input}

  # If depth is 1 (single dot), stay in the current directory
  if [ "$depth" -eq 1 ]; then
    return 0
  fi

  # Construct the relative path based on the number of dots
  local path=""
  for _ in $(seq 1 "$((depth - 1))"); do
    path+="../"
  done

  # Change directory up the calculated number of levels
  cd "$path" || return
}

# Aliases for multiple levels
alias ..='dots ..'
alias ...='dots ...'
alias ....='dots ....'
alias .....='dots .....'
alias ......='dots ......'
