#!/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(){

  docker run --rm -it \
    -v "$(pwd):/var/www/html" \
    -w /var/www/html \
    -u "$(id -u):$(id -g)" \
    --env-file .env \
    -e APP_ENV=${APP_ENV} \
    php ./artisan compose:publish --files docker-compose.yml --files build ${APP_ENV}

}

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(){
  # if $COMPOSE_NETWORK is not set throw error
  if [ -z "$COMPOSE_NETWORK" ]; then
    echo "COMPOSE_NETWORK is not set. Please add it to your .env file."
    exit 1
  fi

  # ensure traefik network exists
  if ! docker network ls | grep -q "traefik"; then
    echo 'Creating traefik network...'
    docker network create $COMPOSE_NETWORK
  fi

  # ensure traefik is running if not
  if ! docker ps -a | grep -q "traefik"; then
    echo 'Starting traefik...'
    dockerCompose --docker \
      -f "$(pwd)/vendor/braceyourself/compose/traefik/docker-compose.yml" \
      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
#############################################

# if command is 'deploy', set APP_ENV to production
if [ "$1" == "deploy" ]; then
  export APP_ENV=production
fi

publishFiles

# Determine the command to run...
case "$1" in
    install)
        echo 'installing node modules'

        # install the node modules
        dockerCompose --docker run --rm npm npm install

        # install the composer dependencies
#        dockerCompose --docker run --rm php 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)"
        ;;
    start)
        shift 1
        setupTraefik

        dockerCompose --docker "up -d --force-recreate --remove-orphans -t0 $*"
        ;;
    up)
        shift 1
        setupTraefik

        dockerCompose --docker "up $*"

        ;;
    down|run|exec|config|ps|logs)
        dockerCompose --docker "$*"
        ;;
    deploy)
        dockerCompose --docker run --rm -it \
          -v "$(pwd):/var/www/html" \
          -v "$HOME:$HOME" \
          -v "$HOME/.ssh:/var/www/.ssh" \
          --entrypoint=php \
          php /var/www/html/artisan \
          compose:deploy
        ;;
    publish)
        dockerCompose /var/www/html/artisan compose:"$*"
        ;;
    *)
        dockerCompose /var/www/html/artisan "$@"
        ;;
esac
