#!/bin/bash

#####
#########
##
## a bunch of this was generated by argbash at argbash.io
##
#########
#####

conda_env_relpath='.xanity/conda_env'
xanity_rc_relpath='.xanity/bashrc'
conda_sh='.xanity/condapath'

### START OF CODE GENERATED BY Argbash v2.6.1 one line above ###

# Argbash is a bash code generator used to get arguments parsing right.
# Argbash is FREE SOFTWARE, see https://argbash.io for more info
# Generated online by https://argbash.io/generate

# When called, the process ends.
# Args:
# 	$1: The exit message (print to stderr)
# 	$2: The exit code (default is 1)
# if env var _PRINT_HELP is set to 'yes', the usage is print to stderr (prior to )
# Example:
# 	test -f "$_arg_infile" || _PRINT_HELP=yes die "Can't continue, have to supply file as an argument, got '$_arg_infile'" 4
die()
{
	local _ret=$2
	test -n "$_ret" || _ret=1
	test "$_PRINT_HELP" = yes && print_help >&2
	echo "$1" >&2
	if [[ -n "${ocwd}" ]]; then
        cd "${ocwd}"
    fi
	exit ${_ret}
}


# Function that evaluates whether a value passed to it begins by a character
# that is a short option of an argument the script knows about.
# This is required in order to support getopts-like short options grouping.
begins_with_short_option()
{
	local first_option all_short_options
	all_short_options='dvh'
	first_option="${1:0:1}"
	test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}


# THE DEFAULTS INITIALIZATION - POSITIONALS
# The positional args array has to be reset before the parsing, because it may already be defined
# - for example if this script is sourced by an argbash-powered script.
_positionals=()
_arg_leftovers=()
# THE DEFAULTS INITIALIZATION - OPTIONALS
_arg_debugger="off"

# Function that prints general usage of the script.
# This is useful if users asks for it, or if there is an argument parsing error (unexpected / spurious arguments)
# and it makes sense to remind the user how the script is supposed to be called.
print_help ()
{
	printf 'Usage: %s [-D|--directory <arg>] [-d|--(no-)debugger] [-v|--version] [-h|--help] <action> ... \n' "$0"
	printf '\t%s\n' "<action>: basic xanity action == <init|setup|run|analyze|id|env>"
	printf '\t%s\n' "-D,--directory: location of xanity project (no default)"
	printf '\t%s\n' "-d,--debugger,--no-debugger: attach any python calls to debugger (off by default)"
	printf '\t%s\n' "-v,--version: Prints version"
	printf '\t%s\n' "-h,--help: Prints help"
}

# The parsing of the command-line
parse_commandline ()
{
	while test $# -gt 0
	do
		_key="$1"
		case "$_key" in
			-d|--no-debugger|--debugger)
				_arg_debugger="on"
				test "${1:0:5}" = "--no-" && _arg_debugger="off"
				;;
			-d*)
				_arg_debugger="on"
				_next="${_key##-d}"
				if test -n "$_next" -a "$_next" != "$_key"
				then
					begins_with_short_option "$_next" && shift && set -- "-d" "-${_next}" "$@" || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option." 1
				fi
				;;

			-D|--directory)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				_arg_directory="$2"
				shift
				;;
			--directory=*)
				_arg_directory="${_key##--directory=}"
				;;
			-D*)
				_arg_directory="${_key##-D}"
				;;

			-v|--version)
				echo "$(pip show -V xanity)"
				exit 0
				;;
			-v*)
				echo "$(pip show -V xanity)"
				exit 0
				;;
#			-h|--help)
#				print_help
#				exit 0
#				;;
#			-h*)
#				print_help
#				exit 0
#				;;
			*)
				_positionals+=("$1")
				;;
		esac
		shift
	done
}


# Check that we receive expected amount positional arguments.
# Return 0 if everything is OK, 1 if we have too little arguments
# and 2 if we have too much arguments
handle_passed_args_count ()
{
	_required_args_string="'action'"
	test ${#_positionals[@]} -ge 1 || _PRINT_HELP=yes die "FATAL ERROR: Not enough positional arguments - we require at least 1 (namely: $_required_args_string), but got only ${#_positionals[@]}." 1
}

# Take arguments that we have received, and save them in variables of given names.
# The 'eval' command is needed as the name of target variable is saved into another variable.
assign_positional_args ()
{
	_positional_names=('_arg_action' )
	_our_args=$((${#_positionals[@]} - ${#_positional_names[@]}))
	for ((ii = 0; ii < _our_args; ii++))
	do
		_positional_names+=("_arg_leftovers[$((ii + 0))]")
	done

	for (( ii = 0; ii < ${#_positionals[@]}; ii++))
	do
		eval "${_positional_names[ii]}=\${_positionals[ii]}" || die "Error during argument parsing, possibly an Argbash bug." 1
	done
}

# Now call all the functions defined above that are needed to get the job done
parse_commandline "$@"
handle_passed_args_count
assign_positional_args

### END OF CODE GENERATED BY Argbash (sortof) ### ])


xanity_enable_conda(){

    ## declare an array variable
    declare -a candidates=("${HOME}/anaconda/etc/profile.d/conda.sh" \
                           "${HOME}/miniconda/etc/profile.d/conda.sh" \
                           "${HOME}/anaconda3/etc/profile.d/conda.sh" \
                           "${HOME}/miniconda3/etc/profile.d/conda.sh" \
                           "${HOME}/anaconda2/etc/profile.d/conda.sh" \
                           "${HOME}/miniconda2/etc/profile.d/conda.sh" )

    exit_msg="could not find conda installation.  please visit https://conda.io/miniconda.html \n"
    exit_msg+="and install miniconda (recommended) or https://conda.io to install the full conda \n"
    exit_msg+="-- if it is installed, make sure it\'s on your path... or otherwise callable :)"

    # check .xanity for path to a conda installation:
    find_xanity_root

    if [[ -r "${XANITY_PROJ_ROOT}/${conda_sh}" ]]; then
        testpath="$(cat ${XANITY_PROJ_ROOT}/${conda_sh})"
        [[ -r "${testpath}" ]] && CONDA_SH="${testpath}"
    fi

    # check to see whether a conda version is installed:
    if [[ -z "${CONDA_SH}" ]] && [[ -n "$_CONDA_EXE" ]]; then
        testpath="${_CONDA_EXE%/*}/../etc/profile.d/conda.sh"
        [[ -r "${testpath}" ]] && CONDA_SH="${testpath}" && echo "using existing conda access"
    fi

    if [[ -z "${CONDA_SH}" ]]; then
        for testpath in "${candidates[@]}"; do
            [[ -r "${testpath}" ]] && CONDA_SH="${testpath}" && echo "using conda: $CONDA_SH"
            [[ -n "${CONDA_SH}" ]] && break
        done
    fi

    [[ -z "${CONDA_SH}" ]] && die "${exit_msg}" 1

    if [[ -n "${CONDA_SH}" ]]; then

      set -a
      source "$CONDA_SH"
      set +a

      export -f conda
      #export -f _conda_activate
      #export -f _conda_deactivate
      #export _CONDA_EXE

      [[ -d .xanity ]] && echo "$CONDA_SH" > "${conda_sh}"
    fi
}

xanity_activate_conda(){

    error_msg="problem entering conda. make sure you've run 'xanity env setup'"

#  if [[ ! -v 'xanity_root' ]]; then
#    if [[ ! -d .xanity ]]; then
#      echo "you're not in a xanity project and you didnt specify one with the -D option"
#      panicandquit
#    fi
#    xanity_root="${PWD}"
#
#  else
#    if [[ ! -d "$xanity_root/.xanity" ]]; then
#      echo 'dir provided is not xanity_root'
#      panicandquit
#    fi
#    export ocwd="${PWD}"
#    cd $xanity_root
#  fi

#  [[ ! -f .xanity/env_state.md5 ]] && die "looks like you're environment is amiss (env hash). Try: 'xanity setup' "\
#        "and then try this again." 1

  # source xanity-enable-conda.sh
  if [[ -n "${XANITY_CONDA_ENV}" ]]; then
      conda activate "${XANITY_CONDA_ENV}" && echo "stepped in to conda env (${XANITY_CONDA_ENV})" \
      || die "${error_msg}" 1

      export XANITY_HOST_VER="$(xanity --version 2>&1 | grep Version | cut -d ' ' -f2)"
  else
        die "${error_msg}" 1
  fi
}

xanity_deactivate_conda(){
  conda deactivate && echo "stepped out of conda env" || { echo "problem exiting conda" && panicandquit ; }
  return status
 }


find_xanity_root(){
    maxlevels=8
    level=0
    owd="${PWD}"

    while [[ ${level} < ${maxlevels} ]]; do
        if [[ -d .xanity ]]; then
            xanity_root="$PWD"
            export XANITY_PROJ_ROOT="$xanity_root"
            export XANITY_CONDA_ENV="${xanity_root}/${conda_env_relpath}"
            export XANITY_PROJ_NAME="$(basename $xanity_root)"
            export XANITY_RC="${xanity_root}/${xanity_rc_relpath}"

            cd "${owd}"
            return 0
        fi
        cd ..
        (( level += 1 ))

    done

    cd "${owd}"
    # echo "not in a xanity project tree."
}

get_in_xanity_root(){
    find_xanity_root
    cd "${XANITY_PROJ_ROOT}" || die "cannot find a xanity root" 1
}

#get_uuid(){
#    UUID="$(cat .xanity/UUID)"
#    [[ -z "$UUID" ]] && die "looks like your setup is amiss (UUID). Try: 'xanity init'; 'xanity setup'"
#    export XANITY_UUID="${UUID}"
#    echo "using UUID = $UUID"
#}

#dir_exist="$( [[ -d ${_arg_directory} ]] )"
#dir_isxanity="$( [[ -d ${_arg_directory}/.xanity ]] )"
#dircheck() { [[ $dir_exist ]] || { printf '%s does not appear to exist' "$_arg_directory"; exit 1; }; }
#xancheck() { [[ $dir_isxanity ]] || { printf '%s is not a valid xanity project' "$_arg_directory"; exit 1; }; }
#xanity_check() { dircheck; xancheck; }


export -f xanity_enable_conda
export -f xanity_activate_conda
export -f xanity_deactivate_conda
#export -f get_uuid

[[ -n "${_arg_directory}" ]] && [[ -d "${_arg_directory}" ]] && cd "${_arg_directory}"

#echo "action as seen by bash script:  ${_arg_action}"

case "$_arg_action" in

    "init")
    
        xanity_enable_conda
        python -m xanity init "${_arg_leftovers[@]}"
    	;;

    "setup")
    
        xanity_enable_conda
        get_in_xanity_root
        python -m xanity setup "${_arg_leftovers[@]}"
        ;;
        
    "run"|"anal"|"analyze"|"analyse")
    
        xanity_enable_conda
        get_in_xanity_root
        xanity_activate_conda
        
        if [[ "$_arg_debugger" == 'on' ]]; then
            python -m pdb -m xanity "$_arg_action" "${_arg_leftovers[@]}"
        else
            python -m xanity "$_arg_action" "${_arg_leftovers[@]}"
        fi
        ;;

    "session"|"sesh"|"sess")

        xanity_enable_conda

        if [[ ! -r "${XANITY_RC}" ]]; then
            literal="\nsource ${CONDA_SH}\n"
            literal+="if conda activate ${XANITY_CONDA_ENV} 2> /dev/null ; then \n"
            literal+="    export PS1=\"\[\033[01;32m\](XANITY:${XANITY_PROJ_NAME})\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\] > \" \n"
            literal+="else\n"
            literal+="    echo \"xanity cannot find a conda environment. have you run xanity setup?\" && exit 1 \n"
            literal+="fi\n"
            printf "${literal}" | cat "${HOME}/.bashrc" - > "${XANITY_RC}"
        fi

        if [[ $# == 1 ]]; then
            bash --rcfile "${XANITY_RC}" -i
        else
            echo "running command in session: ${@:2}"
            bash --rcfile "${XANITY_RC}" -ic  "${@:2}"
        fi
        ;;

#### let python code handle this!!!
#    "list")
#        get_in_xanity_root
#        printf "\nxanity experiments:\n"
#        for item in $(ls experiments | tr -s ' '); do
#
#            if [[ "$item" =~ ^.*[.]py$ ]]; then
#                echo "    $(echo $item | tr -d \'.py\')"
#            fi
#
#        done
#        printf "\n"
#        ;;

    "env")
        # don't get inside conda:
        xanity_enable_conda
        #type conda        
        get_in_xanity_root
        python -m xanity "$_arg_action" "${_arg_leftovers[@]}"
        ;;

    "data")
        # don't get inside conda env:
        xanity_enable_conda
        get_in_xanity_root
        python -m xanity "$_arg_action" "${_arg_leftovers[@]}"
        ;;

    *)
        # everything else
        xanity_enable_conda
        get_in_xanity_root
        xanity_activate_conda
        python -m xanity "$_arg_action" "${_arg_leftovers[@]}"
        ;;
esac

(( $( dirs -p | wc -l ) > 1 )) && popd -0 > /dev/null
exit 0
