#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/auto" || exit 1

function display_help() {
    uecho "$scriptname: outil pour faciliter l'utilisation de docker

USAGE
    $scriptname CMDs...

COMMANDES
    build
    push
    run
    up
    logs
    down
    brd
    ps
    ls
    rm
    prune"
}

function get_version() {
    local GIT_DIR; unset GIT_DIR
    if git rev-parse --git-dir >/dev/null 2>&1; then
        local head commit tag
        commit="$(git rev-list --tags --max-count=1 2>/dev/null)"
        if [ -n "$commit" ]; then
            tag="$(git describe --tags "$commit" 2>/dev/null)"
            if [ -n "$tag" ]; then
                head="$(git rev-parse HEAD)"
                if [ "$commit" != "$head" ]; then
                    echo "$tag-develop"
                else
                    echo "$tag"
                fi
                return
            fi
        fi
    elif [ -f VERSION.txt ]; then
        cat VERSION.txt
    fi
    echo develop
}

function docker_add_build_arg() {
    eval "replace_build_args+=(--build-arg $1=\"$2\"); $1=\"$2\""
}
function docker_parse_build_args() {
    cat "$1" |
    grep -v '^#' |
    grep -v '^$' |
    sed -r 's/([^=]+)=(.*)/replace_build_args+=(--build-arg \1="\2"); \1="\2"/'
}
function docker_parse_env_args() {
    [ -f .build.env ] && eval "$(docker_parse_build_args .build.env)"
    [ -f build.env ] && eval "$(docker_parse_build_args build.env)"
    [ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && eval "$(docker_parse_build_args ".build.$PROFILE.env")"
}
function docker_set_env_args() {
    [ -f .build.env ] && source ./.build.env
    [ -f build.env ] && source ./build.env
    [ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && source "./.build.$PROFILE.env"
}
function docker_set_run_args() {
    replace_run_args+=(--env-file "$1")
    source "$1"
}
function docker_check_name() {
    [ -n "$NAME" ] || die "Vous devez définir NAME dans .build.env"
    if [ "$1" == set_name ]; then
        name="${NAME//[^a-zA-Z0-9_.-]/_}"
    fi
}

function compose_set_env_args() {
    replace_env_args+=(-f docker-compose.yml)
    if [ -f docker-compose.override.yml ]; then
        replace_env_args+=(-f docker-compose.override.yml)
    fi
    local PROJECT_NAME=--none--
    [ -f .compose.env ] && source ./.compose.env
    if [ -n "$PROFILE" ]; then
        if [ -f "docker-compose.$PROFILE.yml" ]; then
            replace_env_args+=(-f "docker-compose.$PROFILE.yml")
        fi
        if [ "$PROJECT_NAME" != --none-- ]; then
            if [ -z "$COMPOSE_PROJECT_NAME" ]; then
                [ -n "$PROJECT_NAME" ] || PROJECT_NAME="$(basename -- "$(pwd)")"
                COMPOSE_PROJECT_NAME="${PROJECT_NAME}_${PROFILE}"
            fi
            export COMPOSE_PROJECT_NAME
        fi
    fi
}

function initialize_build_env() {
    CTXDIR=.
    NAME=
    TAGS=(latest)
    VERSION=
}
function default_update_build_env() {
    [ -n "$VERSION" ] || docker_add_build_arg VERSION "$(get_version)"
    [ -n "$VERSION" ] && TAGS+=("$VERSION")
}
function update_build_env() { default_update_build_env; }

function default_compose_build() {
    docker-compose \
        "${replace_env_args[@]}" "${env_args[@]}" \
        build \
        ${NO_CACHE:+--no-cache} \
        "${replace_build_args[@]}" "${build_args[@]}" \
        "$@"
}
function default_docker_build() {
    local tag
    for tag in "${TAGS[@]}"; do
        replace_build_args+=(-t "$NAME:$tag")
    done
    docker build \
        ${NO_CACHE:+--no-cache} \
        "${replace_env_args[@]}" "${env_args[@]}" \
        "${replace_build_args[@]}" "${build_args[@]}" \
        "$@" "$CTXDIR"
}
function compose_build() { default_compose_build "$@"; }
function docker_build() { default_docker_build "$@"; }
function auto_build() {
    local -a replace_env_args env_args
    local -a replace_build_args build_args
    initialize_build_env
    if [ -f docker-compose.yml ]; then
        compose_set_env_args
        update_build_env
        compose_build
    else
        docker_parse_env_args
        docker_check_name
        docker_add_build_arg build_date "$(date +%y%m%d)"
        update_build_env
        docker_build
    fi
}

function auto_push() {
    local -a replace_env_args env_args
    local -a replace_build_args build_args
    local tag
    initialize_build_env
    if [ -f docker-compose.yml ]; then
        compose_set_env_args
        update_build_env
    else
        docker_parse_env_args
        docker_check_name
        update_build_env
    fi
    for tag in "${TAGS[@]}"; do
        docker push "$NAME:$tag"
    done
}

function default_compose_up() {
    docker-compose \
        "${replace_env_args[@]}" "${env_args[@]}" \
        up "${replace_run_args[@]}" "${run_args[@]}" \
        "${replace_user_args[@]}" "${user_args[@]}" "$@"
}
function default_docker_up() {
    docker run \
           "${replace_env_args[@]}" "${env_args[@]}" \
           "${replace_run_args[@]}" "${run_args[@]}" \
           "$NAME" \
           "${replace_user_args[@]}" "${user_args[@]}" "$@"
}
function compose_up() { default_compose_up "$@"; }
function docker_up() { default_docker_up "$@"; }
function auto_up() {
    local -a replace_env_args env_args
    local -a replace_run_args run_args
    local -a replace_user_args user_args
    if [ -f docker-compose.yml ]; then
        compose_set_env_args
        replace_run_args=(-d)
        compose_up "$@"
    else
        docker_set_env_args
        docker_check_name set_name
        replace_run_args=(-d --name "$name")
        docker_up "$@"
    fi
}

function default_compose_stop() {
    docker-compose \
        "${replace_env_args[@]}" "${env_args[@]}" \
        stop "${replace_stop_args[@]}" "${stop_args[@]}" \
        "$@"
}
function default_docker_stop() {
    docker container stop \
           "${replace_stop_args[@]}" "${stop_args[@]}" \
           "$name" "$@"
}
function compose_stop() { default_compose_stop "$@"; }
function docker_stop() { default_docker_stop "$@"; }
function auto_stop() {
    local -a replace_env_args env_args
    local -a replace_stop_args stop_args
    if [ -f docker-compose.yml ]; then
        compose_set_env_args
        compose_stop "$@"
    else
        docker_set_env_args
        docker_check_name set_name
        docker_stop "$@"
    fi
}

function default_compose_logs() {
    docker-compose \
        "${replace_env_args[@]}" "${env_args[@]}" \
        logs "${replace_logs_args[@]}" "${logs_args[@]}" \
        "$@"
}
function default_docker_logs() {
    docker logs \
           "${replace_logs_args[@]}" "${logs_args[@]}" \
           "$name" "$@"
}
function compose_logs() { default_compose_logs "$@"; }
function docker_logs() { default_docker_logs "$@"; }
function auto_logs() {
    local -a replace_env_args env_args
    local -a replace_logs_args logs_args
    if [ -f docker-compose.yml ]; then
        compose_set_env_args
        replace_logs_args=(-f)
        compose_logs "$@"
    else
        docker_set_env_args
        docker_check_name set_name
        replace_logs_args=(-f)
        docker_logs "$@"
    fi
}

function default_compose_down() {
    docker-compose \
        "${replace_env_args[@]}" "${env_args[@]}" \
        down "${replace_down_args[@]}" "${down_args[@]}" \
        "$@"
}
function default_docker_down() {
    estep "stop"
    docker container stop \
           "${replace_down_args[@]}" "${down_args[@]}" \
           "$name" "$@"
    estep "rm"
    docker container rm \
           "${replace_rm_args[@]}" "${rm_args[@]}" \
           "$name"
}
function compose_down() { default_compose_down "$@"; }
function docker_down() { default_docker_down "$@"; }
function auto_down() {
    local -a replace_env_args env_args
    local -a replace_down_args down_args
    local -a replace_rm_args rm_args
    if [ -f docker-compose.yml ]; then
        compose_set_env_args
        compose_down "$@"
    else
        docker_set_env_args
        docker_check_name set_name
        docker_down "$@"
    fi
}

DEFAULT_PROFILE=devel
PROFILE=
DM_PROFILES=()
set_defaults dk
export PROFILE

if progexists docker-machine; then
    setx active_dm=docker-machine active 2>/dev/null
    for dm_profile in "${DM_PROFILES[@]}"; do
        splitpair "$dm_profile" dm profile
        if [ "$dm" == "$active_dm" ]; then
            DEFAULT_PROFILE="$profile"
            break
        fi
    done
fi

chdir=
NO_CACHE=
args=(
    --help '$exit_with display_help'
    -d:,--chdir: chdir=
    -p:,--profile: PROFILE=
    -P,--prod PROFILE=prod
    -T,--test PROFILE=test
    -j,--no-cache NO_CACHE=1
)
parse_args "$@"; set -- "${args[@]}"

# construire par défaut
[ $# -eq 0 ] && set -- build
[ -n "$PROFILE" ] || PROFILE="$DEFAULT_PROFILE"

[ -n "$chdir" ] && { cd "$chdir" || die; }

while [ $# -gt 0 ]; do
    [ "$1" == -- ] && { shift; continue; }
    cmd="$1"; shift
    case "$cmd" in
    b|build)
        [ -f .build.scripts.sh ] && source ./.build.scripts.sh
        [ -f build.scripts.sh ] && source ./build.scripts.sh
        args=()
        while [ $# -gt 0 -a "$1" != -- ]; do
            args+=("$1"); shift
        done
        enote "Profil $PROFILE"
        auto_build "${args[@]}" || die
        ;;
    push)
        [ -f .build.scripts.sh ] && source ./.build.scripts.sh
        [ -f build.scripts.sh ] && source ./build.scripts.sh
        args=()
        while [ $# -gt 0 -a "$1" != -- ]; do
            args+=("$1"); shift
        done
        enote "Profil $PROFILE"
        auto_push "${args[@]}" || die
        ;;
    s|run|start)
        args=()
        while [ $# -gt 0 -a "$1" != -- ]; do
            args+=("$1"); shift
        done
        enote "Profil $PROFILE"
        auto_up "${args[@]}" || die
        ;;
    k|stop)
        enote "Profil $PROFILE"
        auto_stop || die
        ;;
    1|up)
        args=()
        while [ $# -gt 0 -a "$1" != -- ]; do
            args+=("$1"); shift
        done
        enote "Profil $PROFILE"
        auto_up "${args[@]}" && auto_logs || die
        ;;
    l|logs) auto_logs || die;;
    0|down) auto_down || die;;
    d|brd)
        do_auto_down=1
        function auto_down_trap() {
            [ -n "$do_auto_down" ] && auto_down
        }
        trap auto_down_trap 1 3 15 EXIT

        [ -f .build.scripts.sh ] && source ./.build.scripts.sh
        [ -f build.scripts.sh ] && source ./build.scripts.sh
        args=()
        while [ $# -gt 0 -a "$1" != -- ]; do
            args+=("$1"); shift
        done
        enote "Profil $PROFILE"
        if auto_build; then
            auto_up "${args[@]}" && auto_logs || die
        else
            do_auto_down=
        fi
        ;;
    ps) docker container ps -a || die;;
    ls) docker image ls || die;;
    rm)
        args=()
        while [ $# -gt 0 -a "$1" != -- ]; do
            args+=("$1"); shift
        done
        docker image rm "${args[@]}" || die
        ;;
    X|prune)
        docker container prune -f || die
        docker image prune -f || die
        ;;
    *) die "$cmd: commande inconnue";;
    esac
done