#!/usr/bin/env bash

UNAMEOUT="$(uname -s)"

# Убедитесь, что операционная система поддерживается...
case "${UNAMEOUT}" in
    Linux*)             MACHINE=linux;;
    Darwin*)            MACHINE=mac;;
    *)                  MACHINE="UNKNOWN"
esac

if [ "$MACHINE" == "UNKNOWN" ]; then
    echo "Операционная система не поддерживается [$(uname -s)]. DPOT поддерживает macOS, Linux, and Windows (WSL2)." >&2

    exit 1
fi

# Определить, является ли стандартный вывод терминалом...
if test -t 1; then
    # Определить, поддерживаются ли цвета...
    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

# Функция, которая печатает доступные команды...
function display_help {
    echo "DPOT"
    echo
    echo "${YELLOW}Использование:${NC}" >&2
    echo "  dpot COMMAND [options] [arguments]"
    echo
    echo "Неизвестные команды передаются в docker-compose."
    echo
    echo "${YELLOW}Команды docker-compose:${NC}"
    echo "  ${GREEN}dpot up${NC}        Запуск приложения"
    echo "  ${GREEN}dpot up -d${NC}     Запуск приложения в фоне"
    echo "  ${GREEN}dpot stop${NC}      Остановка приложения"
    echo "  ${GREEN}dpot restart${NC}   Перезапуск приложения"
    echo "  ${GREEN}dpot ps${NC}        Показать статус docker контейнеров"
    echo
    echo "${YELLOW}Команды darksander:${NC}"
    echo "  ${GREEN}dpot darksander ...${NC}          Выполнить darksander команду"
    echo "  ${GREEN}dpot darksander queue:work${NC}"
    echo
    echo "${YELLOW}Команды PHP:${NC}"
    echo "  ${GREEN}dpot php ...${NC}   Выполнить PHP скрипт"
    echo "  ${GREEN}dpot php -v${NC}"
    echo
    echo "${YELLOW}Команды Composer:${NC}"
    echo "  ${GREEN}dpot composer ...${NC}                       Выполнить Composer команду"
    echo "  ${GREEN}dpot composer require darkeum/darklyy-json-attributes${NC}"
    echo
    echo "${YELLOW}Команды Node:${NC}"
    echo "  ${GREEN}dpot node ...${NC}         Выполнить Node команду"
    echo "  ${GREEN}dpot node --version${NC}"
    echo
    echo "${YELLOW}Команды NPM:${NC}"
    echo "  ${GREEN}dpot npm ...${NC}        Выполнить npm команду"
    echo "  ${GREEN}dpot npx${NC}            Выполнить npx command"
    echo "  ${GREEN}dpot npm run prod${NC}"
    echo
    echo "${YELLOW}Команды Yarn:${NC}"
    echo "  ${GREEN}dpot yarn ...${NC}        Выполнить Yarn команду"
    echo "  ${GREEN}dpot yarn run prod${NC}"
    echo
    echo "${YELLOW}Команды дял баз данных:${NC}"
    echo "  ${GREEN}dpot mysql${NC}     Запустить MySQL CLI ссесию для 'mysql' контйнера"
    echo "  ${GREEN}dpot mariadb${NC}   Запустить MySQL CLI ссесию для  'mariadb' контйнера"
    echo "  ${GREEN}dpot psql${NC}      Запустить PostgreSQL CLI ссесию для  'pgsql' контйнера"
    echo "  ${GREEN}dpot redis${NC}     Запустить Redis CLI ссесию для  'redis' контйнера"
    echo
    echo "${YELLOW}Debugging:${NC}"
    echo "  ${GREEN}dpot debug ...${NC}          Выполнить darksander команду в режиме отладки"
    echo "  ${GREEN}dpot debug queue:work${NC}"
    
    exit 1
}

# Прокисрование "help" команд...
if [ $# -gt 0 ]; then
    if [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$1" == "-help" ] || [ "$1" == "--help" ]; then
        display_help
    fi
else
    display_help
fi

# Подключаем исходный файл ".env", чтобы были доступны переменные окружения Darklyy...
if [ -f ./.env ]; then
    source ./.env
fi

# Определение переменных среды...
export APP_PORT=${APP_PORT:-80}
export APP_SERVICE=${APP_SERVICE:-"dpot"}
export DB_PORT=${DB_PORT:-3306}
export WWWUSER=${WWWUSER:-$UID}
export WWWGROUP=${WWWGROUP:-$(id -g)}

export DPOT_FILES=${DPOT_FILES:-""}
export DPOT_SHARE_DASHBOARD=${DPOT_SHARE_DASHBOARD:-4040}
export DPOT_SHARE_SERVER_HOST=${DPOT_SHARE_SERVER_HOST:-"darklyy-dpot.site"}
export DPOT_SHARE_SERVER_PORT=${DPOT_SHARE_SERVER_PORT:-8080}
export DPOTL_SHARE_SUBDOMAIN=${DPOT_SHARE_SUBDOMAIN:-""}

# Функция, которая выводит что DPOT, не запущена...
function dpot_is_not_running {
    echo "${BOLD}DPOT не запущен.${NC}" >&2
    echo "" >&2
    echo "${BOLD}Для запуска можно использовать следующие команды:${NC} './vendor/bin/sail up' or './vendor/bin/sail up -d'" >&2

    exit 1
}

# Определить префикс команды Docker Compose...
docker compose &> /dev/null
if [ $? == 0 ]; then
    DOCKER_COMPOSE=(docker compose)
else
    DOCKER_COMPOSE=(docker-compose)
fi

if [ -n "$DPOT_FILES" ]; then
    # Преобразование DPOT_FILES в массив...
    DPOT_FILES=("${DPOT_FILES//:/ }")

    for FILE in "${DPOT_FILES[@]}"; do
        if [ -f "$FILE" ]; then
            DOCKER_COMPOSE+=(-f "$FILE")
        else
            echo "${BOLD}Не удалось найти файл Docker Compose: '${FILE}'${NC}" >&2

            exit 1
        fi
    done
fi

EXEC="yes"

if [ -z "$DPOT_SKIP_CHECKS" ]; then
    # Убедитесь, что Docker запущен...
    if ! docker info > /dev/null 2>&1; then
        echo "${BOLD}Docker не запущен.${NC}" >&2

        exit 1
    fi

    # Определить, работает ли DPOT...
    if "${DOCKER_COMPOSE[@]}" ps "$APP_SERVICE" 2>&1 | grep 'Exit\|exited'; then
        echo "${BOLD}Отключение старых процессов DPOT...${NC}" >&2

        "${DOCKER_COMPOSE[@]}" down > /dev/null 2>&1

        EXEC="no"
    elif [ -z "$("${DOCKER_COMPOSE[@]}" ps -q)" ]; then
        EXEC="no"
    fi
fi

ARGS=()

# Прокси-команды PHP для двоичного файла «php» в контейнере приложения...
if [ "$1" == "php" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" "php" "$@")
    else
        dpot_is_not_running
    fi

# Бинарные команды поставщика прокси в контейнере приложения...
elif [ "$1" == "bin" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" ./vendor/bin/"$@")
    else
        dpot_is_not_running
    fi

# Прокси-команды docker-compose для двоичного файла docker-compose в контейнере приложения...
elif [ "$1" == "docker-compose" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u sail)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" "${DOCKER_COMPOSE[@]}")
    else
        dpot_is_not_running
    fi

# Команды Proxy Composer для двоичного файла "composer" в контейнере приложения...
elif [ "$1" == "composer" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" "composer" "$@")
    else
        dpot_is_not_running
    fi

# Прокси-команды Darksander для двоичного файла «darksander» в контейнере приложения...
elif [ "$1" == "darksander" ] || [ "$1" == "drs" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" php darksander "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды "debug" в двоичный файл "php darksander" в контейнере приложения с включенным xdebug...
elif [ "$1" == "debug" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot -e XDEBUG_SESSION=1)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" php darksander "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды  "test" в двоичный файл "php darksander test"...
elif [ "$1" == "test" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" php darksander test "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды  "phpunit" в "php vendor/bin/phpunit"...
elif [ "$1" == "phpunit" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" php vendor/bin/phpunit "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды "pint" в "php vendor/bin/pint"...
elif [ "$1" == "pint" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" php vendor/bin/pint "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды "dusk" в "php darksander dusk"...
elif [ "$1" == "dusk" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=(-e "APP_URL=http://${APP_SERVICE}")
        ARGS+=(-e "DUSK_DRIVER_URL=http://selenium:4444/wd/hub")
        ARGS+=("$APP_SERVICE" php darksander dusk "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды "dusk:fails" в "php darksander dusk:fails"  
elif [ "$1" == "dusk:fails" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=(-e "APP_URL=http://${APP_SERVICE}")
        ARGS+=(-e "DUSK_DRIVER_URL=http://selenium:4444/wd/hub")
        ARGS+=("$APP_SERVICE" php darksander dusk:fails "$@")
    else
        dpot_is_not_running
    fi

# Инициировать сеанс Darklyy Tinker в контейнере приложения...
elif [ "$1" == "tinker" ] ; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" php darksander tinker)
    else
        dpot_is_not_running
    fi

# Проксирование команды Node в двоичный файл "node" в контейнере приложения...
elif [ "$1" == "node" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" node "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды NPM в двоичный файл "npm" binary в контейнере приложения...
elif [ "$1" == "npm" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" npm "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды NPX в двоичный файл "npx" binary в контейнере приложения...
elif [ "$1" == "npx" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" npx "$@")
    else
        dpot_is_not_running
    fi

# Проксирование команды YARN в двоичный файл "yarn" binary в контейнере приложения...
elif [ "$1" == "yarn" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" yarn "$@")
    else
        dpot_is_not_running
    fi

# Инициировать сеанс терминала MySQL CLI в контейнере "mysql"...
elif [ "$1" == "mysql" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=(mysql bash -c)
        ARGS+=("MYSQL_PWD=\${MYSQL_PASSWORD} mysql -u \${MYSQL_USER} \${MYSQL_DATABASE}")
    else
        dpot_is_not_running
    fi

# Инициировать сеанс терминала MySQL CLI в контейнере "mariadb"...
elif [ "$1" == "mariadb" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=(mariadb bash -c)
        ARGS+=("MYSQL_PWD=\${MYSQL_PASSWORD} mysql -u \${MYSQL_USER} \${MYSQL_DATABASE}")
    else
        dpot_is_not_running
    fi

# Инициировать сеанс терминала PostgreSQL CLI в контейнере "pgsql"...
elif [ "$1" == "psql" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=(pgsql bash -c)
        ARGS+=("PGPASSWORD=\${PGPASSWORD} psql -U \${POSTGRES_USER} \${POSTGRES_DB}")
    else
        dpot_is_not_running
    fi

# Инициировать оболочку Bash в контейнере приложения...
elif [ "$1" == "shell" ] || [ "$1" == "bash" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec -u dpot)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" bash "$@")
    else
        dpot_is_not_running
    fi

# Инициировать оболочку Bash пользователя root в контейнере приложения...
elif [ "$1" == "root-shell" ] || [ "$1" == "root-bash" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=("$APP_SERVICE" bash "$@")
    else
        dpot_is_not_running
    fi

# Инициировать сеанс терминала Redis CLI в контейнере "redis"...
elif [ "$1" == "redis" ] ; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        ARGS+=(exec)
        [ ! -t 0 ] && ARGS+=(-T)
        ARGS+=(redis redis-cli)
    else
        dpot_is_not_running
    fi

# Поделитесь сайтом...
elif [ "$1" == "share" ]; then
    shift 1

    if [ "$EXEC" == "yes" ]; then
        docker run --init --rm -p "$SAIL_SHARE_DASHBOARD":4040 -t beyondcodegmbh/expose-server:latest share http://host.docker.internal:"$APP_PORT" \
            --server-host="$SAIL_SHARE_SERVER_HOST" \
            --server-port="$SAIL_SHARE_SERVER_PORT" \
            --auth="$SAIL_SHARE_TOKEN" \
            --subdomain="$SAIL_SHARE_SUBDOMAIN" \
            "$@"

        exit
    else
        dpot_is_not_running
    fi

# Передать неизвестные команды в двоичный файл "docker-compose"...
else
    ARGS+=("$@")
fi

# Запустить Docker Compose с заданными аргументами...
"${DOCKER_COMPOSE[@]}" "${ARGS[@]}"