#!/usr/bin/env bash

set -euo pipefail

SELF=$(basename "$0")
COLORS=0
VERBOSE=1

POSITIONALS=()
POSITIONALS_REQUIRED=2

function usage {
    >&2 cat <<HELP
Usage: $SELF [options] input_file output_dir

Options:
    -h, --help      Display help, exit
    -v, --verbose   Be more verbose
    -c, --color     Use colors
HELP
}

function main {
    local input_file="$1"; shift
    local output_dir="$1"; shift
    # business logic here...
}

# Business logic functions here ...

#
# Helpers
#

function log_info {
    [[ $COLORS -eq 1 ]] \
        && echo -e "\e[32m[info] $1\e[0m" \
        || echo "[info] $1"
}

function log_debug {
    [[ $VERBOSE -eq 0 ]] \
        || >&2 echo "[debug] $1"
}

function log_error {
    [[ $COLORS -eq 1 ]] \
        && >&2 echo -e "\e[31m[error] $1\e[0m" \
        || >&2 echo "[error] $1"
}

function exit_usage {
    local code="${1:-99}"; shift || :
    local error_msg="${1:-}"; shift || :
    [[ -z "$error_msg" ]] || log_error "$error_msg"
    usage
    exit "$code"
}

#
# Main plumbing
#

function parse_args {
    local arg="${1:-}"; shift || :
    case "$arg" in
    # Known flags
    -h|--help)      exit_usage 1 ;;
    -v|--verbose)   VERBOSE=1 ;;
    -s|--silent)    VERBOSE=0 ;;
    -c|--color)     COLORS=1 ;;
    # Unknown flag
    -*) exit_usage 5 "unknown flag: $arg" ;;
    # Positional args
    *)  POSITIONALS[${#POSITIONALS[@]}]="$arg" ;;
    esac
    # Recurse to the next arg
    [[ $# -lt 1 ]] || parse_args $@
}

parse_args $@

[[ ${#POSITIONALS[@]} -eq $POSITIONALS_REQUIRED ]] \
    || exit_usage 3 "expecting $POSITIONALS_REQUIRED args, but got ${#POSITIONALS[@]}"

main ${POSITIONALS[@]}