#!/bin/bash


help() {
  cat << EOH

NAME
    $1 - Functional Bash examples

SYNOPSIS
    $1 [-n NUMBER] [-f] ARG ...
    $1 -h

DESCRIPTION
    This script calls Functional Bash functions and outputs their results.

OPTIONS
    -n NUMBER
        example for a numerical value

    -f
        example for a flag (that may be set or unset)

    -h
        This "manual page".

    ARG ...
        Optional remaining command line arguments.

EXAMPLES
    $1
    $1 -f
    $1 -n 42
    $1 -n 42 -f
    $1 -n 42 -f some further arguments
    $1 -h

AUTHOR
    Wolfgang <w6g@wu6ch.de>

LICENSE
    MIT (https://wu6ch.de/bash/functional_bash/LICENSE)

SEE ALSO
    Functional Bash (https://wu6ch.de/bash/functional_bash/)
EOH
}


set_env() {
  source "/usr/local/lib/functional_bash.sh"

  # shellcheck disable=SC2034
  {
    local -A options=()
    local -a remaining_args=()
  }

  get_options "n:f" options remaining_args help "$@" && {
    number="$(get_arg options "n" 0)"
    flag="$(  get_arg options "f"  )"
    remaining_arguments=("${remaining_args[@]}")

    declare -gr number flag remaining_arguments
  }
}


output_aligned() {
  put_aligned "." 18 "$1" "$2"
}


put_settings() {
  echo
  output_aligned "settings" "'$-'"
  output_aligned "settings" "'$SHELLOPTS'"
}


put_args() {
  echo
  is_set "$flag" ; output_aligned "args: flag" "$(put_cond "un" "" $?)set"
  output_aligned "args: number" "$number"
  output_aligned "args: remainig" "$(list "${remaining_arguments[@]}" | show_list)"
}


use_get_script_name() {
  echo
  output_aligned "get_script_name" "$(get_script_name)"
  output_aligned "get_script_name" "$(script_name="hugo" get_script_name)"
}


use_put_cond() {
  echo
  (( 1 >= 2 )) ; output_aligned "put_cond" "$(put_cond "less" "greater or equal" $?)"
  (( 2 >= 2 )) ; output_aligned "put_cond" "$(put_cond "less" "greater or equal" $?)"
}


use_put_aligned() {
  echo
  output_aligned "put_aligned" "$(put_aligned "~" 10 "abc"   "xyz")"
  output_aligned "put_aligned" "$(put_aligned "~" 10 "de"    "xyz")"
  output_aligned "put_aligned" "$(put_aligned "~" 10 "fghij" "xyz")"
}


use_get_minint_get_maxint() {
  echo
  output_aligned "get_minint" "$(get_minint)"
  output_aligned "get_maxint" " $(get_maxint)"
}


use_get_min_get_max() {
  echo
  output_aligned "get_min" "$(get_min 42 41)"
  output_aligned "get_max" "$(get_max 42 41)"
}


use_lminval_lmaxval() {
  echo
  output_aligned "lminval" "$( list 3 42 13 66 7 | lminval)"
  output_aligned "lmaxval" "$( list 3 42 13 66 7 | lmaxval)"
}


use_lminlen_lmaxlen() {
  echo
  output_aligned "lminlen" "$( list "ABC" "A" "AB" "ABCDE" "ABCD" | lminlen)"
  output_aligned "lmaxlen" "$( list "ABC" "A" "AB" "ABCDE" "ABCD" | lmaxlen)"
}


use_list_to_array() {
  local array=()
  list_to_array array < <(list "X" "Y" "Z")
  echo
  output_aligned "list_to_array" "$(list "${array[@]}" | show_list)"
}


use_to_array() {
  local array=()
  to_array array "X" "Y" "Z"
  output_aligned "to_array" "$(list "${array[@]}" | show_list)"
}


use_lmap() {
  _use_lmap_func() {
    echo "<$1>"
  }

  echo
  output_aligned "lmap" "$(list "a" "b" "c" | lmap _use_lmap_func | show_list)"
}


use_lapply() {
  _use_lapply_func_1() {
    (( $2 % 2 != 0 )) && echo "$1:$2"
  }

  _use_lapply_func_2() {
    (( $2 % 2 == 0 )) && echo "$1:$2"
  }

  # shellcheck disable=SC2034
  local f_array=(
    "$(to_tuple "_use_lapply_func_1" "o")"
    "$(to_tuple "_use_lapply_func_2" "e")"
  )

  output_aligned "lapply" "$(lapply f_array < <(seq 0 9) | show_list)"
}


use_lbind() {
  _use_lbind_func() {
    echo "$1"
    echo "$(($1 * 10))"
    echo "$(($1 * 100))"
  }

  output_aligned "lbind" "$(list "1" "2" "3" | lbind _use_lbind_func | show_list)"
}


use_lfilter() {
  _use_lfilter_func() {
    (( $1 % 2 != 0 ))
  }

  echo
  output_aligned "lfilter" "$(seq 1 20  | lfilter _use_lfilter_func | show_list)"
}


use_lfilter_nonhash() {
  output_aligned "lfilter_nonhash" "$(list \
      "  # comment " \
      " valid  " \
      "also valid # comment" \
    | lfilter_nonhash | show_list)"
}


use_lfoldl() {
  _use_lfoldl_func() {
    (( ($2 % 2) == 0 ))
    put_cond "$(($1 + $2))" "$1" $?
  }

  echo
  output_aligned "lfoldl" "$(list 1 1 2 3 4 6 | lfoldl 0 _use_lfoldl_func)"
}


use_lscanl() {
  _use_lscanl_func() {
    (( ($2 % 2) == 0 ))
    put_cond "$(($1 + $2))" "$1" $?
  }

  output_aligned "lscanl" "$(list 1 1 2 3 4 6 | lscanl 0 _use_lfoldl_func | show_list)"
}


use_lfoldm() {
  _use_lfoldm_func() {
    local rval out
    (( $1 > 0 )) ; rval=$?
    out="$(put_cond "$(get_unset)" "$2" $rval)"
    to_pair "$(($1 + 1))" "$out"
  }

  output_aligned "lfoldm" "$(list "a" "b" "c" | lfoldm 0 _use_lfoldm_func | show_list)"
}


use_lunfoldr() {
  _use_lunfoldr_func() {
    (( $2 <= $1 )) && to_pair "$2" "$(($2 + 1))"
  }

  output_aligned "lunfoldr" "$(lunfoldr 1 _use_lunfoldr_func 10 | show_list)"
}


fibonacci() {
  _fib_gen() {
    local left  ; left="$( tfst "$2")"
    local right ; right="$(tsnd "$2")"
    local sum   ; sum=$((left + right))

    (( sum <= $1 )) && to_pair "$sum" "$(to_pair "$right" "$sum")"
  }

  output_aligned "fibonacci" "$(lunfoldr "$(to_pair 0 1)" _fib_gen 987 | lprepend 0 1 | show_list)"
}


use_to_tuple() {
  echo
  output_aligned "to_tuple" "$(show_tuple "$(to_tuple "1" "2" "3" "4")")"
}


use_split_at() {
  output_aligned "split_at" "$(show_tuple "$(split_at "=" "hugo = egon lisa")")"
}


use_tnth() {
  output_aligned "tnth" "$(tnth 6 "$(to_tuple "a" "b" "c" "d" "e" "f")")"
}


use_swap_pair() {
  output_aligned "swap_pair" "$(show_tuple "$(swap_pair "$(to_tuple "left" "right")")")"
}


use_tmap() {
  local in_tuple out_tuple

  _use_tmap_func() {
    echo $(($1 * 1000))
    false
  }

  in_tuple="$(to_tuple "1" "2" "3" "4")"
  out_tuple="$(tmap "$in_tuple" _use_tmap_func)"

  output_aligned "tmap" "$(show_tuple "$out_tuple")"
}


use_tuple_to_list() {
  output_aligned "tuple_to_list" "$(tuple_to_list "$(to_tuple "I" "II" "III" "IV")" | show_list)"
}


use_is_subset() {
  # shellcheck disable=SC2034
  local my_array=( "Hugo" "Egon" "Lisa" )
  local rval

  echo

  is_subset my_array < <(list "Lisa" "Hugo") ; rval=$?
  output_aligned "is_subset" "array $(put_cond "does not contain" "contains" $rval) list as subset"

  is_subset my_array < <(list "Lisa" "Fritz") ; rval=$?
  output_aligned "is_subset" "array $(put_cond "does not contain" "contains" $rval) list as subset"
}


use_intersection() {
  # shellcheck disable=SC2034
  local my_array=( "Hugo" "Egon" "Lisa" )

  output_aligned \
    "intersection" \
    "$(intersection my_array < <(list "Lisa" "Fritz" "Hugo") | show_list)"
}


use_split_to_array() {
  local array=()
  split_to_array "abc de f" " " array
  output_aligned "split_to_array" "$(list "${array[@]}" | show_list)"
}


use_amap() {
  # shellcheck disable=SC2034
  local -A assoc=( ["a"]="A" ["b"]="B" ["c"]="C" )

  _use_amap_func() {
    echo "key=$1/value=$2"
  }

  echo
  output_aligned "amap" "$(amap assoc _use_amap_func | sort | show_list)"
}


use_zipwith() {
  # shellcheck disable=SC2034
  {
    local left=( "a" "b" "c" "d" )
    local right=( "1" "2" "3" )
  }

  _use_zipwith_func() {
    echo "$1/$2"
  }

  output_aligned "zipwith" "$(zipwith left right _use_zipwith_func | show_list)"
}


use_get_conf() {
  # shellcheck disable=SC2034
  local -A conf=()

  _config() {
    cat << EOC
  # comment
key1=value1
key-2 = value-2
 key 3  =  "value 3"
key_4 = value_4  # comment
key_5 = value_5a value_5b \
        value_5c
key_6 = value 6
EOC
  }

  get_conf conf < <(_config)
  _show_assoc() { echo "key=$1/value=$2"; }
  echo; output_aligned "get_conf" "$(amap conf _show_assoc | sort | show_list)"
}


set_env "$@" \
  \
  && put_settings \
  && put_args \
  \
  && use_get_script_name \
  && use_put_cond \
  && use_put_aligned \
  \
  && use_get_minint_get_maxint \
  && use_get_min_get_max \
  && use_lminval_lmaxval \
  && use_lminlen_lmaxlen \
  \
  && use_list_to_array \
  && use_to_array \
  && use_lmap \
  && use_lapply \
  && use_lbind \
  && use_lfilter \
  && use_lfilter_nonhash \
  && use_lfoldl \
  && use_lscanl \
  && use_lfoldm \
  && use_lunfoldr \
  && fibonacci \
  \
  && use_to_tuple \
  && use_split_at \
  && use_tnth \
  && use_swap_pair \
  && use_tmap \
  && use_tuple_to_list \
  \
  && use_is_subset \
  && use_intersection \
  && use_split_to_array \
  && use_amap \
  && use_zipwith \
  \
  && use_get_conf


# EOF - vim:cc=101
