#!/usr/bin/env bash
#############################################
# Compose for Laravel
#############################################

UNAMEOUT="$(uname -s)"

# Verify operating system is supported...
case "${UNAMEOUT}" in
    Linux*)             MACHINE=linux;;
    Darwin*)            MACHINE=mac;;
    *)                  MACHINE="UNKNOWN"
esac

if [ "$MACHINE" == "UNKNOWN" ]; then
    echo "Unsupported operating system [$(uname -s)]. Compose for Laravel supports macOS, Linux, and Windows (WSL2)." >&2

    exit 1
fi

# Determine if stdout is a terminal...
if test -t 1; then
    # Determine if colors are supported...
    ncolors=$(tput colors)

    if test -n "$ncolors" && test "$ncolors" -ge 8; then
        BOLD="$(tput bold)"
        YELLOW="$(tput setaf 3)"
        GREEN="$(tput setaf 2)"
        NC="$(tput sgr0)"
    fi
fi

#############################################
# Argument Parsing
#############################################

# Proxy the "help" command...
if [ $# -gt 0 ]; then
    if [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$1" == "-help" ] || [ "$1" == "--help" ]; then
        display_help
    fi
else
    display_help
fi

# shellcheck source=/dev/null
if [ -n "$APP_ENV" ] && [ -f ./.env."$APP_ENV" ]; then
  source ./.env."$APP_ENV";
elif [ -f ./.env ]; then
  source ./.env;
fi

#############################################
# Functions
#############################################


# Function that prints the available commands...
display_help(){
    echo "Compose for Laravel"
    echo
    echo "${YELLOW}Usage:${NC}" >&2
    echo "  compose COMMAND [options] [arguments]"
    echo
    echo "Unknown commands are passed to artisan"
    echo
    echo "${YELLOW}Commands:${NC}"
    echo "  ${GREEN}compose restart${NC}   Restart the application"
    echo "  ${GREEN}compose migrate${NC}   Run the application's database migrations"
    echo
    echo "${YELLOW}All other commands are passed to artisan${NC}"
    exit 1
}

#publish the compose file using ./artisan compose:publish
publishFiles(){
  # use docker-compose if docker-compose.yml file exists
  if [ -f docker-compose.yml ]; then
    dockerCompose --docker run --rm -it \
      --entrypoint bash \
      -u "$(id -u):$(id -g)" \
      php -c "./artisan compose:publish --files docker-compose.yml --files build"
  else
    docker run --rm -it \
      -v "$(pwd):/var/www/html" \
      -w /var/www/html \
      -u "$(id -u):$(id -g)" \
      php ./artisan compose:publish --files docker-compose.yml --files build
  fi
}

dockerCompose(){
  exe=""
  options=""

  if command -v docker compose &> /dev/null
  then
      exe="docker compose"
  else
      exe="docker-compose"
  fi

  exe="$exe $options"

  if [ "$1" == '--docker' ]; then
    shift 1
    $exe "$@"
    return 0
  fi

  # check if docker-compose php service is running
  if $exe ps --services | grep -q "php"; then
    exe="$exe exec php"
  else
    exe="$exe run --rm --entrypoint=php php"
  fi

  $exe "$@"
}

setupTraefik(){
  # ensure traefik network exists
  if ! docker network ls | grep -q "traefik"; then
    echo 'Creating traefik network...'
    docker network create traefik
  fi

  # ensure traefik is running
  if ! docker ps --filter "name=traefik" | grep -q "traefik"; then
    echo "Starting traefik..."
    dockerCompose  up -d
  fi
}

spin(){
  # first arg is the message
  # remaining args are the command to run
  message=$1
  shift

  $* 2>/dev/null &

  pid=$! # Process Id of the previous running command

  spin='-\|/'

  i=0
  while kill -0 $pid 2>/dev/null
  do
    i=$(( (i+1) %4 ))
    printf "\r${spin:$i:1}$message"
    sleep .1
  done
}


#############################################
# Main
#############################################

publishFiles
setupTraefik

# Determine the command to run...
case "$1" in
    install)
        echo 'installing node modules'
        # install the node modules
        dockerCompose --docker run --rm -it \
          --entrypoint bash \
          npm -c "npm install"

        # install the composer dependencies
        dockerCompose --docker run --rm -it \
          --entrypoint bash \
          php -c "composer install"

      ;;
    build)
        # build the application
        dockerCompose --docker build \
          --build-arg HOME="$HOME" \
          --build-arg USER_ID="$(id -u)" \
          --build-arg GROUP_ID="$(id -g)"
        ;;

    deploy)
        dockerCompose --docker run --rm -it --entrypoint=php php /var/www/html/artisan compose:deploy
        ;;
    publish)
        dockerCompose /var/www/html/artisan compose:"$*"
        ;;
    up|down|run|exec|config|ps|logs)
        # pass the command to docker compose
        dockerCompose --docker "$@"
        ;;
    *)
        dockerCompose /var/www/html/artisan "$@"
        ;;
esac