#!/bin/bash
# Desc: Processes script arguments

#==BEGIN Define script parameters==
#===BEGIN Define variables===
:
declare -ag arrayPosArgs
#===END Define variables===

#===BEGIN Declare local script functions===
yell() { echo "$0: $*" >&2; }      #o Yell, Die, Try Three-Fingered Claw technique
die() { yell "$*"; exit 111; }     #o Ref/Attrib: https://stackoverflow.com/a/25515370
try() { "$@" || die "cannot $*"; } #o
vbm() {
    # Description: Prints verbose message ("vbm") to stderr if opVerbose is set to "true".
    # Usage: vbm "DEBUG :verbose message here"
    # Version 0.2.0
    # Input: arg1: string
    #        vars: opVerbose
    # Output: stderr
    # Depends: bash 5.1.16, GNU-coreutils 8.30 (echo, date)

    if [ "$opVerbose" = "true" ]; then
	functionTime="$(date --iso-8601=ns)"; # Save current time in nano seconds.
	echo "[$functionTime]:$0:""$*" 1>&2;  # Display argument text.
    fi

    # End function
    return 0; # Function finished.
} # Displays message if opVerbose true
showUsage() {
    # Desc: Display script usage information
    # Usage: showUsage
    # Version 0.0.2
    # Input: none
    # Output: stdout
    # Depends: GNU-coreutils 8.30 (cat)
    cat <<'EOF'
    USAGE:
        bktemp-processArgs [ options ] [FILE...]

    OPTIONS:
        -h, --help
                Display help information.
        --version
                Display script version.
        -v, --verbose
                Display debugging info.
        -i, --input-file
                Define input file path.
        -I, --input-dir
                Define input directory path.
        -o, --output-file
                Define output file path.
        -O, --output-dir
                Define output directory path.
        --
                Indicate end of options.

    EXAMPLE:
      bktemp-processArgs -o foo.txt
      bktemp-processArgs -o foo.txt -- some_file.txt
EOF
} # Display information on how to use this script.
showVersion() {
    # Desc: Displays script version and license information.
    # Usage: showVersion
    # Version: 0.0.2
    # Input: scriptVersion   var containing version string
    # Output: stdout
    # Depends: vbm(), yell, GNU-coreutils 8.30

    # Initialize function
    vbm "DEBUG:showVersion function called."

    cat <<'EOF'
bktemp-processArgs 1.0.0
Copyright (C) 2021 Steven Baltakatei Sandoval
License GPLv3: GNU GPL version 3
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

    GNU Coreutils 8.32
    Copyright (C) 2020 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
EOF
    
    # End function
    vbm "DEBUG:showVersion function ended."
    return 0; # Function finished.
} # Display script version.
processArgs() {
    # Desc: Processes arguments provided to script.
    # Usage: processArgs "$@"
    # Version: 1.0.0
    # Input: "$@"          (list of arguments provided to the function)
    # Output: Sets following variables used by other functions:
    #   opVerbose            Indicates verbose mode enable status.  (ex: "true", "false")
    #   pathDirOut1          Path to output directory.
    #   pathFileOut1         Path to output file.
    #   pathDirIn1           Path to input directory.
    #   pathFileIn1          Path to input file.
    #   opFileOut1_overwrite Indicates whether file pathFileOut1 should be overwritten (ex: "true", "false").
    #   arrayPosArgs         Array of remaining positional argments
    # Depends:
    #   yell()           Displays messages to stderr.
    #   vbm()            Displays messsages to stderr if opVerbose set to "true".
    #   showUsage()      Displays usage information about parent script.
    #   showVersion()    Displays version about parent script.
    #   arrayPosArgs     Global array for storing non-option positional arguments (i.e. arguments following the `--` option).
    # External dependencies: bash (5.1.16), echo
    # Ref./Attrib.:
    #  [1]: Marco Aurelio (2014-05-08). "echo that outputs to stderr". https://stackoverflow.com/a/23550347
    #  [2]: "Handling positional parameters" (2018-05-12). https://wiki.bash-hackers.org/scripting/posparams

    # Initialize function
    vbm "DEBUG:processArgs function called."

    # Perform work
    while [ ! $# -eq 0 ]; do   # While number of arguments ($#) is not (!) equal to (-eq) zero (0).
	#yell "DEBUG:Starting processArgs while loop." # Debug stderr message. See [1].
        #yell "DEBUG:Provided arguments are:""$*"      # Debug stderr message. See [1].
	case "$1" in
	    -h | --help) showUsage; exit 1;; # Display usage.
	    --version) showVersion; exit 1;; # Show version
	    -v | --verbose) opVerbose="true"; vbm "DEBUG:Verbose mode enabled.";; # Enable verbose mode. See [1].
	    -i | --input-file) # Define input file path
		if [ -f "$2" ]; then # If $2 is file that exists, set pathFileIn1 to $2, pop $2.
		    pathFileIn1="$2";
		    shift;
		    vbm "DEBUG:Input file pathFileIn1 set to:""$2";
		else
		    yell "ERROR: Specified input file does not exist:""$2";
		    yell "Exiting.";
		    exit 1;
		fi ;; 
	    -I | --input-dir) # Define input directory path
		if [ -d "$2" ]; then # If $2 is dir that exists, set pathDirIn1 to $2, pop $2.
		    pathDirIn1="$2";
		    shift;
		    vbm "DEBUG:Input directory pathDirIn1 set to:""$2";
		else # Display error if $2 is not a valid dir.
		    yell "ERROR:Specified input directory does not exist:""$2";
		    yell "Exiting.";
		    exit 1;
		fi ;; 
	    -o | --output-file) # Define output file path
		if [ -f "$2" ]; then # If $2 is file that exists, prompt user to continue to overwrite, set pathFileOut1 to $2, pop $2.
		    yell "Specified output file $2 already exists. Overwrite? (y/n):"
		    read -r m; case $m in
				y | Y | yes) opFileOut1_overwrite="true";;
				n | N | no) opFileOut1_overwrite="false";;
				*) yell "Invalid selection. Exiting."; exit 1;;
			    esac
		    if [ "$opFileOut1_overwrite" == "true" ]; then
			pathFileOut1="$2";
			shift;
			vbm "DEBUG:Output file pathFileOut1 set to:""$2";
		    else
			yell "ERORR:Exiting in order to not overwrite output file:""$pathFileOut1";
			exit 1;
		    fi
		else
		    pathFileOut1="$2";
		    shift;
		    vbm "DEBUG:Output file pathFileOut1 set to:""$2";
		fi ;;
	    -O | --output-dir) # Define output directory path
		if [ -d "$2" ]; then # If $2 is dir that exists, set pathDirOut1 to $2, pop $2
		    pathDirOut1="$2";
		    shift;
		    vbm "DEBUG:Output directory pathDirOut1 set to:""$2";
		else
		    yell "ERROR:Specified output directory is not valid:""$2";
		    yell "Exiting.";
		    exit 1;
		fi ;;
            --) # End of all options. See [2].
                shift;
                for arg in "$@"; do
                    vbm "DEBUG:adding to arrayPosArgs:$arg";
                    arrayPosArgs+=("$arg");
                done;
                break;;
            -*) showUsage; yell "ERROR: Unrecognized option."; exit 1;; # Display usage
	    *) showUsage; yell "ERROR: Unrecognized argument."; exit 1;; # Handle unrecognized options. See [1].
	esac
	shift
    done

    # End function
    vbm "DEBUG:processArgs function ended."
    return  0; # Function finished.
} # Evaluate script options from positional arguments (ex: $1, $2, $3, etc.).

#===END Declare local script functions===
#==END Define script parameters==

#==BEGIN sample code==
processArgs "$@";
yell "DEBUG:Provided arguments..:""$*" 
yell "DEBUG:opVerbose...........:${opVerbose:-<unset>}";
yell "DEBUG:pathDirOut1.........:${pathDirOut1:-<unset>}";
yell "DEBUG:pathFileOut1........:${pathFileOut1:-<unset>}";
yell "DEBUG:pathDirIn1..........:${pathDirIn1:-<unset>}";
yell "DEBUG:pathFileIn1.........:${pathFileIn1:-<unset>}";
yell "DEBUG:opFileOut1_overwrite:${opFileOut1_overwrite:-<unset>}";
yell "DEBUG:arrayPosArgs........:$(if [[ -v arrayPosArgs ]]; then declare -p arrayPosArgs; else printf "<unset>"; fi )";
#yell "DEBUG:arrayPosArgs........:${arrayPosArgs[*]}";
#==END sample code==

# Author: Steven Baltaktei Sandoval
# License: GPLv3+