#!/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

path.usage() # # prints the usage information for path commands
{
  local this=${0##*/}
  echo "You started
$0

  Usage:
  $this: command   description and Parameter

      usage        prints this dialog while it will print the status when there are no parameters

      status       checks the OOSH and ONCE cofiguration
      env          prints the environment variable and updates result.env
      list         lists all paths line by line

      add
      push
      append       all append the provided <path> to the PATH and update the config

      put
      prepend      all prepend the provided <path> to the PATH and update the config

      rm
      remove       all remove all occurences of the provided <path> from the PATH and update the config

      file.global  lists the paths in /etc/paths
      file.user                    in ~/paths
      file.custom                  in <file>

      load          loads the paths from ~/paths
      save          saves the PATH    to ~/paths


  Examples
    $this list
    $this append /usr/local/bin
    $this prepend /my/custom/path
    $this remove /old/path
  "
}

path.list() # # lists all PATH entries line by line
{
  #loop list PATH print "$1"
    echo $PATH \
  | line.split ":"
}

path.env() # # returns the PATH as an export statement in RESULT
{
  create.result 0 "export PATH=$PATH" "$1"
  console.log "
          $RESULT
  "
  return $(result save)
}

path.file.global() # # lists the system-wide path config from /etc/paths
{
  cat /etc/paths
}

path.file.global.use () { # # copies the systems path config as a user path config
  cp /etc/paths ~/paths
}

path.file.user() { # # lists the users path config
  cat ~/paths
}

path.save() { # # exports the current path into a user file
  path.file.user.save
}

path.edit() { # # edits the paths user file
  path.file.user.edit
}

path.load() { # # restores the current path from a user file
  path.file.user.set
}

path.file.user.save() { # # exports the current path into a user file
  echo $PATH \
    | line.split ":" \
    | line.unquote >~/paths
}

path.file.user.edit() { # # exports the current path into a user file
  vim ~/paths
}

path.file.user.set() { # # restores the current path from a user file
  cat ~/paths \
    | line.quote \
    | line.join ":" \
    | line.into PATH

  private.update.config
  # source $CONFIG_PATH/result.env 

  # echo "new PATH:
  # $PATH"

  # config save
  # config list
}


path.file.custom() { # <file> # lists the custom path config
  cat "$1"
}

path.sync() # # syncs PATH between OOSH and ONCE configurations
{
  once path.use.oosh
  path.status
}

path.status() # # checks if OOSH and ONCE PATH configurations are in sync
{
  check message "if ${CYAN}oosh${NO_COLOR} is configuring the PATH" file $CONFIG exists call path show.oosh.path
  #result.load
  source $CONFIG_PATH/result.env
  local _oosh_path="$RESULT"


  check message "if ${CYAN}once${NO_COLOR} is configuring the PATH" file ~/.once exists call path show.once.path
  source $CONFIG_PATH/result.env
  local _once_path="$RESULT"


  console.log "
Result:
  "

  if ! [ "$_oosh_path" == "$_once_path" ]; then
    warn.log "
  STATUS: paths are not equal
    OOSH: $_oosh_path
    ONCE: $_once_path
    "
    path.env
    source $CONFIG_PATH/result.env
    local _current_path="$RESULT"
    if [ "$_oosh_path" == "$_current_path" ]; then
      success.log " PATH is equal to OOSH configuration"
    fi
    if [ "$_once_path" == "$_current_path" ]; then
      warning.log "PATH is equal to ONCE configuration"
    fi
  else
    success.log "
   STATUS: all well configured
    "
  fi

}

path.show.once.path() # # displays the PATH from ONCE config file ~/.once
{
  #this.absolutePath ~/.once
  silent.log "ONCE config from: $HOME/.once"
  local _once_path="export $(cat ~/.once | grep 'PATH=')"

  create.result 0 "$_once_path" "$1"
  echo "$RESULT"
  return $(result save)
}

path.show.oosh.path() # # displays the PATH from OOSH config file
{
  #this.absolutePath ~/.once
  silent.log "OOSH config from: $CONFIG"
  create.result 0 "$(cat $CONFIG | grep '^export PATH=')" "$1"
  echo "$RESULT"
  return $(result save)
}


path.add() # <dir> # appends dir to PATH and saves config (alias for append)
{
  path.append "$*"
}

path.push() # <dir> # appends dir to PATH and saves config (alias for append)
{
  path.append "$*"
}

path.put() # <dir> # prepends dir to PATH and saves config (alias for prepend)
{
  path.prepend "$*"
}

path.rm() # <dir> # removes dir from PATH and saves config (alias for remove)
{
  path.remove "$*"
}

path.append() # <dir> # appends dir to the end of PATH, removes duplicates, and saves config
{
  #loop list PATH add "$1" result
  echo $PATH \
  | line.split ":" \
  | line.quote \
  | line.filter "$1" \
  | line.add "$1" \
  | line.join ":"\
  | line.into PATH

  shift
  private.update.config
  RETURN=$1
}

path.prepend() # <dir> # prepends dir to the beginning of PATH, removes duplicates, and saves config
{
  #loop $PATH : put "$1" result
  echo $PATH \
  | line.split ":" \
  | line.quote \
  | line.filter "$1" \
  | line.prepend "$1" \
  | line.join ":"\
  | line.into PATH


  shift
  private.update.config
  RETURN=$1
}

path.remove() # <dir> # removes all occurrences of dir from PATH and saves config
{
  echo $PATH \
  | line.split ":" \
  | line.quote \
  | line.remove "$1" \
  | line.join ":" \
  | line.into PATH

  shift
  private.update.config
  RETURN=$1
}




private.update.config() # # internal: saves PATH to user config and displays instructions
{
  source $CONFIG_PATH/result.env
  if [ -z "list" ]; then
    PATH=$list
  fi
  config save
  config list
  success.log "


  Path updated in OOSH config:  $CONFIG

  new PATH is: $PATH

  to apply to the current shell please type:
    reconfigure
  or
    r
  or
    c
  "

}

private.pathadd() # <dir> <?position:before> # internal: adds dir to PATH if not already present
{
    if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$1($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH="$PATH:${1%/}"
        else
            PATH="${1%/}:$PATH"
        fi
    fi
}

private.pathrm() # <dir> # internal: removes dir from PATH using sed
{
    PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}


path.parameter.completion.dir() # <prefix> # completion function for <dir> parameter - returns matching directories
{
  compgen -d "$1"
}

# ── Directory completions for path manipulation methods ─────────────────
path.add.completion.dir() { compgen -d "$1"; }
path.push.completion.dir() { compgen -d "$1"; }
path.rm.completion.dir() { compgen -d "$1"; }
path.append.completion.dir() { compgen -d "$1"; }
path.prepend.completion.dir() { compgen -d "$1"; }
path.remove.completion.dir() { compgen -d "$1"; }

path.start() # <?args> # initializes path script and dispatches to requested method
{
  #echo "sourcing init"
  source this
  source line
  #source config

  # if [ -z "$1" ]; then
  #   status.discover "$@"
  #   return 0
  # fi

  this.start "$@"
}

path.start "$@"
