#!/usr/bin/env bash

#
# @param ONLY_ENV=
# @param -w|--watch
# @param --shell
# @param --flags pre-release
# @params for pytest
# @params for ptw
# @params for pytest-snapshot: --snapshot-update
#

die() {
  echo "ERROR: $1"
  exit 1
}

args_counter=$#
while [ $args_counter -ne 0 ]; do  
  arg=$1
  shift
  args_counter=$((args_counter-1))

  case "$arg" in
    "--flags")
      while [ $args_counter -ne 0 ]; do
        next_arg=$1
        shift
        args_counter=$((args_counter-1))
        
        case $next_arg in
          -*)
            set -- "$next_arg" "$@"
            args_counter=$((args_counter+1))
            break
            ;;
        esac

        OPT_FLAGS="$OPT_FLAGS $next_arg"
      done
      ;;

    *)
      set -- "$@" "$arg"
  esac
done


PROJECT_DIR=$(pwd)
prj_name=$(basename "$PROJECT_DIR")
DEFAULT_RUN_OPTS="--mount type=bind,source=$PROJECT_DIR,target=/src --workdir /src"

shopt -s globstar nullglob dotglob

[ ! -z "$ONLY_ENV" ] && echo "! ENV filter: $ONLY_ENV"

for env_launcher in ./**/env_*/start; do
  env_dir=$(dirname $env_launcher)
  env_name=$(basename $env_dir)
  launch_tests_cmd="$env_launcher $@"

  if [ ! -z "$ONLY_ENV" ] && [ "$ONLY_ENV" != "$env_name" ]; then
    echo ". skip $env_dir"
    continue
  fi

  echo -e "\n\n###########"
  echo "## Testing: $env_dir..."
  echo "###########"

  is_any_docker=0
  for dockerfile_path in $env_dir/Dockerfile*; do
    dockerfile=$(basename $dockerfile_path)

    flags=""
    require_image=""
    run_opts=$DEFAULT_RUN_OPTS
    opts_file="$env_dir/opts-$dockerfile"
    [ -e "$opts_file" ] && . $opts_file

    flags_intersection=$(dev/lists-intersection -a $OPT_FLAGS -b $flags)

    if [ ! -z "$flags" ] && [ -z "$flags_intersection" ]; then
      echo ". skip $dockerfile: doesn't match flags: $flags (use --flags)"
      continue
    fi

    if [ "$dockerfile" == "Dockerfile" ]; then
      flags_intersection=$(dev/lists-intersection -a $OPT_FLAGS -b no-default)
      if [ ! -z "$flags_intersection" ]; then
        echo ". skip $dockerfile (flag: no-defaultf)"
        continue
      fi
    fi
    target_python_version=$(cat $PROJECT_DIR/.python-version)

    echo "| $dockerfile (target python: $target_python_version, flags: $flags, require_image: $require_image)"

    common_build_opts="--build-arg ARG_PYTHON_VERSION=$target_python_version \
      --build-arg ARG_USER=$(id -u --name) \
      --build-arg ARG_UID=$(id -u)"

    if ! [ -z "$require_image" ]; then
      required_dockerfile_path="$env_dir/Dockerfile.$require_image"

      [ -e "$required_dockerfile_path" ] || die "require_image=$require_image, but file $required_dockerfile_path not found!"

      require_image_tag="python-$target_python_version"
      required_image_name="${prj_name}__${env_name}__${require_image}:$require_image_tag"

      echo -n "> docker build required $required_image_name..."
      image_id=$(docker build -q \
        $common_build_opts \
        -f $required_dockerfile_path -t $required_image_name $PROJECT_DIR \
      )
      echo " done ($image_id)"
    fi

    echo -n "> docker build..."
    image_id=$(docker build -q \
      $common_build_opts \
      --build-arg ARG_REQUIRED_IMAGE="$required_image_name" \
      -f $dockerfile_path $PROJECT_DIR \
    )
    echo " done ($image_id)"

    echo "| run_opts: $run_opts"
    echo "> docker run..."
    docker run --rm $(echo $run_opts) \
      --env PYTEST_LAUNCHER_VIRTUAL_ENV=1 \
      -it $image_id /bin/bash -lc "$launch_tests_cmd"
    is_any_docker=1
  done

  if [ $is_any_docker -eq 0 ]; then
    echo "! No Dockerfile for $env_dir"
    echo "> start locally"
    $env_launcher $@
  fi
done
