#!/usr/bin/env bash


APPLICATION_DIRNAME="application"
# GIT_REPO=git@gitlab.com:gilles1/jeu_concours.git
QUEUES=""

THIS_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

set -e
if [ ! -d "${THIS_SCRIPT_DIR}" ]
  then echo "Error: Script directory(${THIS_SCRIPT_DIR}) does not exist";
  exit -1;
fi;

ROOT_DIR="${THIS_SCRIPT_DIR}"
APPLICATION_DIR="${THIS_SCRIPT_DIR}/${APPLICATION_DIRNAME}"
ENV_DIR="${THIS_SCRIPT_DIR}/docker/env"
BACKUP_DIR="${THIS_SCRIPT_DIR}/backups"
VOLUMES_DIR="${THIS_SCRIPT_DIR}/volumes"

ENV=${2:-"dev"}

echo "--- environment: $ENV"
echo ""

start(){
    dc $ENV up -d app
}

wait_for(){
  dc $ENV run --rm -e "DOMAIN=$1" -e "PORT=$2" wait-for
}

stop(){
    dc $ENV down
}


# docker compose wrapper
# dc <env> <command>
dc(){
  $(which docker) compose -f ./docker-compose.common.yml -f ./docker-compose.${1}.yml "${@: 2}"
}

# php composer wrapper
# composer <env> <command>
composer(){
  dc $ENV run --rm fpm composer "${@: 2}"
}

# php artisan wrapper
# artisan <env> <command>
artisan(){
  dc $ENV run --rm fpm ./artisan "${@: 2}" 
}

# laravel migrate shorctut
# db_migrate <env>
db_migrate(){
  dc $ENV run --rm fpm ./artisan migrate 
}

# laravel migrate shorctut
# db_rollback <env>
db_rollback(){
  dc $ENV run --rm fpm ./artisan migrate:rollback
}

# remove all docker volumes
# prune_volumes <env>
prune_volumes(){
  dc $ENV down -v --remove-orphans
  rm -fr ./volumes/*
}

# prune local application, this includes removing all volumes and application source files
# prune_local <env>
prune_local(){
  prune_volumes $ENV
  # rm -fr ${APPLICATION_DIR}

}

# prune application (image based), this includes removing all volumes
prune_prod(){
  echo "This will remove all content files and database ?"
  read -p "Do you want to remove all applications content " -n 1 -r
  echo ""
  if [[ $REPLY =~ ^[Yy]$ ]]
  then
    prune_volumes $ENV
    echo "All content removed"
  fi
}

# prune application, this includes removing all volumes
# prune <env>
prune(){
  if [ "$ENV" == "prod" ]; then
    prune_prod
  else 
    prune_local
  fi
}

# install application libraries
# install_app <env>
install_app(){
    start ${ENV} 
    composer ${ENV} install
}

# migrate application (database)
# migrate_app <env>
migrate_app(){
  start ${ENV}
  if [ "$ENV" != "prod" ]; then
    wait_for "db" "3306"
  fi
  db_migrate ${ENV}
}

# start application job queues
# start_queues <env>
start_queues(){
  if [ ! -z "$QUEUES" ]; then
    dc $ENV up -d $QUEUES
  fi
}

# stop application job queues
# stop_queues <env>
stop_queues(){
  if [ ! -z "$QUEUES" ]; then
    dc $ENV stop $QUEUES
    dc $ENV rm -f $QUEUES
  fi
}

# install infrastructure : volumes, images, ...
# it will not erased exiting content
# install <env>
install(){
  create_volumes_dir
  install_app
}

# prune application, this includes removing all volumes
# prune <env>
prune(){
  stop
  if [ "$ENV" == "prod" ]; then
    prune_prod
  else 
    prune_local
  fi
}


# update application : install, migrate
# update_app <env>
update_app(){
  stop $ENV
  if [ "$ENV" != "dev" ]; then
    # ask user to confirm if we wants to rebuild images
    
    read -p "Do you want to rebuild images " -n 1 -r
    echo ""
    if [[ $REPLY =~ ^[Yy]$ ]]
    then
      build_images
    fi
  fi
  install_app
  migrate_app
  start $ENV
}

# build images helper for non local environment
# _build_images <env> <branch> <commit>
_build_images(){
  

  cp ./docker/env/env.$ENV ${APPLICATION_DIR}/.env
  docker build -t ${APPLICATION_DIRNAME}/php -f ./docker/php.dockerfile ./docker
  docker build -t ${APPLICATION_DIRNAME}/nginx -f ./docker/nginx.dockerfile ./docker
}

# build custom images for non local environment
# build_images <env> <commit>
build_images(){
  # take second argument or HEAD if not provided
  
  if [ "$ENV" == "prod" ]; then
    _build_images $ENV master $2
  else 
    _build_images $ENV $ENV $2
  fi
}

# create volumes sub directory
# create_volumes_dir
create_volumes_dir(){
  # mkdir if not exists
  mkdir -p $VOLUMES_DIR/db/dumps
  mkdir -p $VOLUMES_DIR/db/mysql
  mkdir -p $VOLUMES_DIR/files
  mkdir -p $VOLUMES_DIR/logs
}


# $1 filename to source for environment variables
_load_env() {
  set -a
  source "${ENV_DIR}/env.$1"
  set +a
}

local_db_start_and_wait(){
  if [ "$ENV" != "prod" ]; then
    dc $ENV up -d db
    wait_for "db" "3306" "3306"
  fi
}

# seed database database from file
# files needs to be located in ./volumes/db/seeds
db_seed(){


  local_db_start_and_wait
 
  _load_env $1
  echo "Seeding database from $2 $DB_USERNAME $DB_PASSWORD $DB_HOST $DB_DATABASE"
  dc $ENV run --rm mysql-cli mysql --port=$DB_PORT --user=$DB_USERNAME --password=$DB_PASSWORD --host=$DB_HOST $DB_DATABASE  -e "source  /var/data/db/seeds/$2"
  echo "Database seeded from $2"
}

# import database from file
# files needs to be located in ./volumes/db/dumps
# db_import <env> <filename>
db_import(){
  local_db_start_and_wait
  _load_env $1
  dc $ENV run --rm mysql-cli mysql --port=$DB_PORT --user=$DB_USERNAME --password=$DB_PASSWORD --host=$DB_HOST $DB_DATABASE  -e "source  /var/data/db/dumps/$2"
  echo "Database seeded from $2"
}

# dump database to file
# files will be located in ./volumes/db/dumps/<date>-<filename>
# db_dump <env> <filename>
db_dump(){
  _load_env $1
  local_db_start_and_wait
  compressed=$3
  # store current time in string 
  now=$(date +"%Y_%m_%d_%H_%M_%S")
  # if compressed has any value

  dc $ENV run --rm mysql-cli mysqldump --no-tablespaces --set-gtid-purged=OFF --port=$DB_PORT --user=$DB_USERNAME --password=$DB_PASSWORD --host=$DB_HOST --databases $DB_DATABASE -r ./var/data/db/dumps/$now-$2

  filepath=$VOLUMES_DIR/db/dumps/$now-$2

  if [ "$compressed" == "1" ]; then
    # compress generated file and remove original
    gzip $filepath
    filepath=$filepath.gz
  fi

  # get last created file of the directory using ls
  filepath=$(ls -t $VOLUMES_DIR/db/dumps | head -1)

  echo "Database dumped to"
  echo "$filepath"

  # dc $ENV run --rm mysql-cli mysqldump --no-tablespaces --set-gtid-purged=OFF --port=$DB_PORT --user=$DB_USERNAME --password=$DB_PASSWORD --host=$DB_HOST --databases $DB_DATABASE -r ./var/data/db/dumps/$now-$2
}

# mysql-cli wrapper : include environment based credentials
# db_cli <env> <command>
db_cli(){
  _load_env $1
  dc $ENV run --rm mysql-cli mysql --port=$DB_PORT --user=$DB_USERNAME --password=$DB_PASSWORD --host=$DB_HOST $DB_DATABASE $2
}

# clean install : prune, build images, install, seed, start
# clean_install <env>
clean_install(){
  mkdir -p $BACKUP_DIR
  mkdir -p $VOLUMES_DIR

  echo "! This will erase all content"
  read -p "Do you want to do a clean install ? " -n 1 -r
  echo ""
  if [[ $REPLY =~ ^[Yy]$ ]]; then
    prune
    if [ "$ENV" != "dev" ]; then
      build_images
    fi
    
    cp ./docker/env/env.$ENV ${APPLICATION_DIR}/.env
    install
    db_seed $ENV "seed.sql"
    db_migrate $ENV
    start
    
  fi
}

# do a db backup in provided directory
# db_backup <env> <dirname>
db_backup(){
  _load_env $ENV
  dirname=$2
  compressed=$3
  dc $ENV run --rm mysql-cli mysqldump --no-tablespaces  --set-gtid-purged=OFF --port=$DB_PORT --user=$DB_USERNAME --password=$DB_PASSWORD --host=$DB_HOST --databases $DB_DATABASE -r $BACKUP_DIR/$dirname/backup.sql

  if [ "$compressed" == "1" ]; then
    # compress generated file and remove original
    gzip $BACKUP_DIR/$dirname/backup.sql
  fi
}

# do a content backup in provided directory
# content_backup <env> <dirname>
content_backup(){
  dirname=$2
  cd $VOLUMES_DIR
  tar -czvf $BACKUP_DIR/$dirname/files.tar.gz ./files
  tar -czvf $BACKUP_DIR/$dirname/logs.tar.gz ./logs
  cd $ROOT_DIR
}

# do a complete app data backup in provided directory, default : ./backups/<date>-backup
# backup <env> <dirname>
backup(){
  dir_suffix=${2:-"backup"}
  date=$(date +"%Y-%m-%d_%H%M")
  dirname="$date-$dir_suffix"
  mkdir -p $BACKUP_DIR/$dirname

  echo "Backing up database"
  db_backup $ENV $dirname
  echo "Backing up content"
  content_backup $ENV $dirname
  echo "Backup done"
}

app_export_entries(){
  _load_env $ENV
  dc $ENV run --rm fpm php artisan entries:export
  # ask user to confirm if we wants to wipe db
  read -p "Do you want to wipe database ? " -n 1 -r
  echo ""
  if [[ $REPLY =~ ^[Yy]$ ]]
  then
    db_dump $ENV entries.sql
    artisan $ENV db:wipe
    artisan $ENV migrate
  fi
}

# if no method provided display doc
if [ $# -eq 0 ];
  then
    echo "No arguments supplied"
    echo "Usage: ./dc.sh <command> <env>"
    echo "Commands:"
    echo "-- App"
    echo "  app_export_entries <env> : export entries and wipe database"
    echo "-- Docker"
    echo "  start <env> : start docker containers"
    echo "  stop <env> : stop docker containers"
    echo "  prune <env> : remove all docker volumes"
    echo "  build_images <env> : build custom images for non local environment"
    echo "-- App"
    echo "  start_queues <env> : start application job queues"
    echo "  stop_queues <env> : stop application job queues"
    echo "  migrate_app <env> : migrate application (database)"
    echo "  db_migrate <env> : migrate database"
    echo "  db_rollback <env> : migrate rollback"
    echo "  artisan <env> <command> : php artisan wrapper"
    echo "  composer <env> <command> : php composer wrapper"
    echo "  install_app <env> : install application libraries"
    echo "  backup <env> <dirname> : do a complete app data backup in provided directory, default : ./backups/<date>-backup"
    echo "  update_app <env> : update application : install, migrate"
    echo "  clean_install <env> : clean install : prune, build images, install, seed, start"
    echo "-- DB"
    echo "  db_seed <env> <filename> : seed database database from file"
    echo "  db_dump <env> <filename> : dump database to file"
    echo "  db_import <env> <filename> : import database from file"
    echo "  db_cli <env> <command> : mysql-cli wrapper : include environment based credentials"
else
  "$@"
fi

