#!/bin/bash

# =============================================================================
# Bash CLI Argument Parser — Greedy Grouping, Flag-Agnostic
# =============================================================================
#
# Overview:
#   Parses command-line arguments into key/value groups.
#   Every flag (long or short) collects values until the next flag.
#   You do NOT need to define which flags expect values.
#   Short flags can be grouped (-abc) and are treated as booleans.
#
# Supported input formats:
#   --key value1 value2         → key = [value1, value2]
#   --key=value                 → key = value
#   -k value                    → k = value
#   -k=value                    → k = value
#   -abc                        → a=true, b=true, c=true
#
#  Not supported:
#   -kvalue                    → this is parsed as combined short flags (k, v, a…)
#   Global positionals not linked to any flag (can be added separately if needed)
#
#  Example usage:
#   ./arg_analyse.sh --mode fast --files input1.txt input2.txt -vx --output=result.txt
#
#   Output:
#     --mode:
#       [0]: fast
#     --files:
#       [0]: input1.txt
#       [1]: input2.txt
#     --v:
#       [boolean flag]
#     --x:
#       [boolean flag]
#     --output:
#       [0]: result.txt
#
# =============================================================================

# STORAGE: key = flag name, value = string or boolean
declare -A FLAG_GROUPS

# -----------------------------------------------------------------------------
# FUNCTION: parse_grouped_args
# Description:
#   Parses input arguments and fills the FLAG_GROUPS associative array.
# -----------------------------------------------------------------------------
parse_grouped_args() {
  local current_flag=""
  local -a current_values=()

  while [[ $# -gt 0 ]]; do
    local token="$1"

    # -------------------------------------------------------------------------
    # Case 1: --key=value or -k=value (explicit assignment form)
    # This handles both long and short flags passed as --flag=value or -f=value
    # -------------------------------------------------------------------------
    # Breakdown of regex:
    # ^          → start of the string
    # --?        → match one or two dashes (e.g. "-" or "--")
    # ([^=]+)    → capture group 1: one or more characters that are NOT "="
    #              → this becomes the flag name (e.g. "output")
    # =          → literal equals sign
    # (.*)       → capture group 2: any number of characters (can be empty)
    #              → this becomes the first value for the flag
    #
    # Examples:
    #   --file=abc.txt  → key = "file", val = "abc.txt"
    #   -x=1            → key = "x", val = "1"
    if [[ "$token" =~ ^--?([^=]+)=(.*)$ ]]; then
      # Before processing this --flag=value, we must flush any previous group
      if [[ -n "$current_flag" ]]; then
        if [[ ${#current_values[@]} -eq 0 ]]; then
          FLAG_GROUPS["$current_flag"]="true"
        else
          FLAG_GROUPS["$current_flag"]="${current_values[*]}"
        fi
      fi

      # Capture the key and value from the current --key=value or -k=value
      local key="${BASH_REMATCH[1]}" # group 1 from regex (flag name)
      local val="${BASH_REMATCH[2]}" # group 2 from regex (value after =)

      # Set current flag context to continue collecting values if any follow
      current_flag="$key"
      current_values=("$val") # start a new value group with first value from assignment

    # -------------------------------------------------------------------------
    # Case 2: --long flag (starts a new group)
    # -------------------------------------------------------------------------
    elif [[ "$token" == --* ]]; then
      # Save previous flag (if any)
      if [[ -n "$current_flag" ]]; then
        if [[ ${#current_values[@]} -eq 0 ]]; then
          FLAG_GROUPS["$current_flag"]="true"
        else
          FLAG_GROUPS["$current_flag"]="${current_values[*]}"
        fi
      fi
      current_flag="${token#--}" # Remove leading "--"
      current_values=()

    # -------------------------------------------------------------------------
    # Case 3: -short or -grouped flags (-x or -abc)
    # -------------------------------------------------------------------------
    elif [[ "$token" == -* && "$token" != "--" ]]; then
      # Save previous group
      if [[ -n "$current_flag" ]]; then
        if [[ ${#current_values[@]} -eq 0 ]]; then
          FLAG_GROUPS["$current_flag"]="true"
        else
          FLAG_GROUPS["$current_flag"]="${current_values[*]}"
        fi
        current_flag=""
        current_values=()
      fi

      local chars="${token#-}"

      if [[ "${#chars}" -gt 1 ]]; then
        # -abc → treat each letter as a boolean flag
        for ((i = 0; i < ${#chars}; i++)); do
          FLAG_GROUPS["${chars:i:1}"]="true"
        done
      else
        # Single short flag (-x) may collect values
        current_flag="$chars"
        current_values=()
      fi

    # -------------------------------------------------------------------------
    # Case 4: Value (non-flag)
    # -------------------------------------------------------------------------
    else
      current_values+=("$token")
    fi

    shift
  done

  # Final flush (for last group)
  if [[ -n "$current_flag" ]]; then
    if [[ ${#current_values[@]} -eq 0 ]]; then
      FLAG_GROUPS["$current_flag"]="true"
    else
      FLAG_GROUPS["$current_flag"]="${current_values[*]}"
    fi
  fi
}

# -----------------------------------------------------------------------------
# FUNCTION: print_grouped_args
# Description:
#   Pretty-prints the FLAG_GROUPS key/value structure.
# -----------------------------------------------------------------------------
print_grouped_args() {
  echo "Parsed Arguments:"
  for key in "${!FLAG_GROUPS[@]}"; do
    IFS=' ' read -r -a values <<<"${FLAG_GROUPS[$key]}"
    echo "--$key:"
    if [[ "${FLAG_GROUPS[$key]}" == "true" ]]; then
      echo "  [boolean flag]"
    elif [[ ${#values[@]} -eq 0 ]]; then
      echo "  [empty]"
    else
      for i in "${!values[@]}"; do
        echo "  [$i]: ${values[$i]}"
      done
    fi
  done
}

# -----------------------------------------------------------------------------
# TEST CASE (for development)
# Comment this out to use real CLI args
# -----------------------------------------------------------------------------
#set -- --name Kerem yollu siki --age=33 --flag -vx --output result.txt -t alpha beta

# Run parser and print results
#parse_grouped_args "$@"
#print_grouped_args
