#!/usr/bin/env bash

# LACKADAISICAL CLI

# Environment Setup
LD_CONFIG_FOLDER="${LD_CONFIG_FOLDER:-$HOME/.config/lackadaisical}"
LD_ALIASFILE="${LD_ALIASFILE:-$LD_CONFIG_FOLDER/aliases.src}"
LD_EDITORFILE="${LD_EDITORFILE:-$LD_CONFIG_FOLDER/editor.src}"
LD_ESOURCEFILE="${LD_ESOURCEFILE:-$LD_CONFIG_FOLDER/extra.src}"

if [[ -z "$LD_FOLDER" ]]; then
  LD_FOLDER=$(dirname "$(realpath "$0")")
fi

ld_dbg()
{
  if [[ $_LD_DEBUG == 1 ]]; then
    echo "DEBUG: $*" >&2
  fi
}

# --- Internal Utils ---

_daisy_wait_for_editor()
{
  local pname="$1"
  local fname="$2"
  sleep 1
  while true; do
    alive=$(pgrep -f "$pname.*$fname")
    if [[ $alive == "" ]]; then
      break
    fi
    sleep 1
  done
}

_daisy_editor()
{
  local editor=${LD_EDITOR:-$EDITOR}
  ld_dbg "Opening $editor to edit file: $1"
  $editor "$1"
  sleep 1
  _daisy_wait_for_editor "$editor" "$1"
}

_daisy_enc()
{
  local enc_is_folder="${ENC_IS_FOLDER:-0}"
  if [ -t 0 ] && [ -z "$1" ]; then
    echo "# $0: No arguments or stdin specified!"
    return 1
  fi

  if [ ! -t 0 ] && [ -z "$1" ]; then
    echo "# $0: Please provide a filename as argument when using stdin"
    return 1
  fi

  if [ -n "$1" ] && [ -d "$1" ]; then
    echo -e "daisy_create_folder=$1"
  else
    local file_dir=""
    local file_name=""
    local perms=755
    local target=$1

    if [[ ! -t 0 ]] && [[ $enc_is_folder == 0 ]]; then
      file_dir="."
      file_name="$1"
    elif [ -f "$1" ]; then
      file_dir=$(dirname "$1")
      file_name=$(basename "$1")
      perms=$(stat -c %a "$1")
    else
      echo "# $0: An error occured during encoding."
      return 1
    fi

    local base64_inner
    base64_inner=$(cat "${1:-/dev/stdin}" | base64 | tr -d '\n')
    echo -e "daisy_folder_$file_name=$file_dir"
    echo -e "daisy_data_base64_$file_name=\"$base64_inner\""
    echo -e "daisy_perms_$file_name=$perms"
  fi
}

_daisy_dec()
{
  if [ -t 0 ] && [ -z "$1" ]; then
    echo "$0: No arguments or stdin specified!"
    return 1
  fi
  local data
  data=$(cat "${1:-/dev/stdin}" | grep -v "#")
  echo -e "$data" | cut -d "=" -f 2- | cut -b 2- | head -c -2 | base64 -d
}

_daisy_unalias()
{
  local unalias_param="$1"
  if [[ $unalias_param =~ ^[0-9]+$ ]]; then
    unalias_param=$(head -"$unalias_param" "$LD_ALIASFILE" 2>/dev/null | tail -1 | cut -d "=" -f 1 | awk '{print $2}')
  fi
  if [[ -z "$unalias_param" ]]; then
    return
  fi
  if [[ -f "$LD_ALIASFILE" ]]; then
    local newdata
    newdata=$(grep -v "alias $unalias_param" "$LD_ALIASFILE" 2>/dev/null)
    cp "$LD_ALIASFILE" "$LD_ALIASFILE.bak" 2>/dev/null
    echo -e "$newdata" > "$LD_ALIASFILE"
  fi
}

# --- Command Functions ---

cmd_help()
{
  local target_tool="$1"
  local file="$LD_FOLDER/README.md"
  if [[ ! -f "$file" ]]; then
    echo "README.md not found at $file"
    exit 1
  fi
  sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
  if [ -z "$target_tool" ]; then
    cat
  else
    awk -v query="$target_tool" '
      BEGIN { found=0; printing=0 }
      $0 ~ /^[[:space:]]*- / {
        printing=0
        sig = $0
        sub(/^[[:space:]]*- /, "", sig)
        sub(/:[[:space:]]*$/, "", sig)
        split(sig, names, "/")
        is_match = 0
        if (sig == query) is_match = 1
        else {
          for (i in names);
          do
            if (names[i] == query) { is_match = 1; break }
          done
        }
        if (is_match) {
          printing=1
          found=1
          print $0
          next
        }
      }
      printing {
        if ($0 ~ /^[[:space:]]*- /) { printing=0; next }
        print
      }
      END {
        if (found == 0) {
          print "Tool '\''" query "'\'' not found in README.md."
        }
      }
    '
  fi
}

cmd_list()
{
  local file="$LD_FOLDER/README.md"
  if [[ ! -f "$file" ]]; then
    echo "README.md not found at $file"
    exit 1
  fi
  echo "Available LACKADAISICAL commands:"
  sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
  awk '
      /^[[:space:]]*- / {
          sub(/^[[:space:]]*- /, "");
          sub(/:[[:space:]]*$/, "");
          print "  " $0
      }
  ' | sort
}

cmd_enc()
{
  case "$1" in
    multi)
      shift
      for f in "$@"; do _daisy_enc "$f"; done
      ;;
    folder)
      if ! command -v tree >/dev/null 2>&1; then
        echo "This function requires the utility 'tree'. Please install it."
        exit 1
      fi
      shift
      local dir="$1"
      if [[ ! -d "$dir" ]]; then
        echo "Directory not found: $dir"
        exit 1
      fi
      cd "$dir" || exit 1
      tree -fia --noreport . | sed 1d | while read -r item; do
        ENC_IS_FOLDER=1 _daisy_enc "$item"
      done
      ;;
    *)
      _daisy_enc "$@"
      ;;
  esac
}

cmd_dec()
{
  case "$1" in
    multi)
      shift
      local arg1=$1
      local arg2=$2
      if [ ! -t 0 ]; then
        arg2=$1
        arg1=/dev/stdin
      fi
      [[ -t 0 ]] && [[ ! -f "$arg1" ]] && echo "daisy dec multi: No input file specified" && exit 1
      [[ ! -d "$arg2" ]] && echo "daisy dec multi: No output directory specified" && exit 1

      local folder=""
      while IFS= read -r line; do
        if [[ "$line" == "daisy_create_folder="* ]]; then
          folder=$(echo "$line" | cut -d "=" -f 2)
          mkdir -p "$arg2/$folder"
        elif [[ "$line" == "daisy_folder"* ]]; then
          folder=$(echo "$line" | cut -d "=" -f 2)
        elif [[ "$line" == "daisy_data_base64"* ]]; then
          local file=$(echo "$line" | cut -d "_" -f 4- | cut -d "=" -f 1)
          mkdir -p "$arg2/$folder"
          _daisy_dec <(echo "$line") > "$arg2/$folder/$file"
        elif [[ "$line" == "daisy_perms"* ]]; then
          local file=$(echo "$line" | cut -d "_" -f 3- | cut -d "=" -f 1)
          local perms=$(echo "$line" | cut -d "_" -f 3- | cut -d "=" -f 2)
          chmod "$perms" "$arg2/$folder/$file"
        fi
      done < "$arg1"
      ;;
    *)
      _daisy_dec "$@"
      ;;
  esac
}

cmd_alias()
{
  local alias_param="$*"
  if [[ -z "$alias_param" ]]; then
    echo "Active lackadaisical alias lines:"
    local linenum=1
    if [[ -f "$LD_ALIASFILE" ]]; then
      while IFS= read -r line; do
        line=$(echo "$line" | sed 's/alias //g')
        echo "$linenum: $line"
        ((linenum++))
      done < "$LD_ALIASFILE"
    fi
  else
    local alias_name=$(echo "$alias_param" | grep -o ".*=" | tr -d =)
    if [[ $alias_name =~ ^[0-9]+$ ]]; then
      echo "An alias cannot start with a number! Exiting."
      exit 1
    fi
    _daisy_unalias "$alias_name"
    echo "alias ${alias_param%=*}=\"${alias_param#*=}\"" >> "$LD_ALIASFILE"
  fi
}

cmd_clear()
{
  find "$LD_CONFIG_FOLDER" -name "*.src" -type f | while read -r f; do
    cp -R "$f" "$f.bak"
    echo "Removing config file: $f"
    rm -rf "$f"
  done
  echo "Config cleared. Use 'daisy restore' if you would like to undo this."
}

cmd_restore()
{
  find "$LD_CONFIG_FOLDER" -name "*.src.bak" -type f | while read -r f; do
    local target="${f%.bak}"
    cp -R "$f" "$target"
    rm -rf "$f"
    echo "Restored backup: $target <-- $f"
  done
  echo "Config restored. Backups have been retained."
}

cmd_combine()
{
  local cmds=()
  local args=()
  local separator_found=false

  for item in "$@"; do
    if [[ "$item" == "--" ]]; then
      separator_found=true
      continue
    fi

    if $separator_found; then
      args+=("$item")
     else
       cmds+=("$item")
     fi
  done

  for cmd in "${cmds[@]}"; do
    set -- "${args[@]}"
    eval "$cmd"
  done
}

# --- Dispatcher ---

case "$1" in
  help)    shift; cmd_help "$@" ;;
  list)    shift; cmd_list "$@" ;;
  enc)     shift; cmd_enc "$@" ;;
  dec)     shift; cmd_dec "$@" ;;
  alias)   shift; cmd_alias "$@" ;;
  unalias) shift; _daisy_unalias "$@" ;;
  backup)  shift; find "$LD_CONFIG_FOLDER" -name "*.src" -type f | while read -r f; do cp -R "$f" "$f.bak"; echo "Backup made: $f --> $f.bak"; done ;;
  clear)   shift; cmd_clear ;;
  restore) shift; cmd_restore ;;
  combine) shift; cmd_combine ;;
  editor)  shift; _daisy_editor "$@" ;;
  wait)
    if [[ "$2" == "for" && "$3" == "editor" ]]; then
      shift 3
      _daisy_wait_for_editor "$@"
    else
      echo "Unknown daisy command: wait $*"
      exit 1
    fi
    ;;
  reload)
    LD_INTERNAL=0 source "$LD_SOURCE_FILE"
    ;;
  *)
    echo "Unknown daisy command: $1"
    exit 1
    ;;
esac
