#!/bin/bash -x

action=$1

CURL="curl --unix-socket /var/run/docker.sock"
RUN_DIR="/run/unas-docker"
JOB_DIR="$RUN_DIR/create/$JOB_ID"
CONF_FILE="$JOB_DIR/conf"
INFO_FILE="$JOB_DIR/info"
ENV_FILE="$JOB_DIR/.env"

LAST_ERROR=/run/unas-docker/create/lasterror

curl_opt(){
    url="http://localhost/containers/create?name=$container"
}

prepare_(){
    echo Prepare to install

    # Prepare environment vars
    cd $WORK_DIR
    if [ "$TYPE" == "yaml" ];then
        eval $(yq -r '.services[].environment[]' "$CONF_FILE" 2>/dev/null | sort | uniq | sed 's/^/export /')
        for env_file in $(yq -r '.services[].env_file[]' "$CONF_FILE" 2>/dev/null | sort | uniq);do
            if [ -f "$env_file" ]; then
                cat "$env_file" >> $ENV_FILE
                # An extra EOF
                echo >> $ENV_FILE
                export $(cat "$env_file" | xargs)
            else
                echo Invalid env_file: "$env_file" > $LAST_ERROR
                exit 1
            fi
        done
    fi

}

pull() {
    image0=$(eval echo $1)
    if [ "$FORCE_PULL"n != 1n ] && docker inspect $image0 >/dev/null;then
        image_target="$image0"
        return 0
    fi
    image_escaped=`systemd-escape $image0`
    image_proxy=`/unas/sbin/docker/pull prepare $image_escaped | grep -E '^NAS DOCKER PULL TAGNAME: '`
    if echo $image_proxy | grep -qE '^NAS DOCKER PULL TAGNAME: ';then
        image_target=${image_proxy#NAS DOCKER PULL TAGNAME: }
    else
        return 1
    fi

    if [ "$FORCE_PULL"n == 1n ] || ! docker inspect $image_target >/dev/null;then
        systemctl start unas-docker-pull@$image_escaped.service
    else
        echo Image $image_target exists
    fi

    if docker inspect $image_target >/dev/null ;then
        return 0
    else
        echo Pull $image0 failed
        return 1
    fi
}

image_required() {
    case "$TYPE" in
        json)
            jq -r .Image "$CONF_FILE"
            ;;
        yaml)
            yq -r '.services[].image' "$CONF_FILE"
            ;;
        cmd)
            ;;
        *)
            echo Unknown type: "$TYPE"
            exit 1
            ;;
    esac
}

image_update() {
    case "$TYPE" in
        json)
            jq -c ". |= if .Image == \"$1\" then .Image = \"$2\" else . end" "$CONF_FILE" > "$CONF_FILE.tmp"
            mv "$CONF_FILE.tmp" "$CONF_FILE"
            ;;
        yaml)
            yq -i --yaml-output ".services[] |= (select(.image == \"$1\").image = \"$2\")" "$CONF_FILE"
            ;;
        cmd)
            ;;
        *)
            echo Unknown type: "$TYPE"
            exit 1
            ;;
    esac
}

containers() {
    case "$TYPE" in
        json)
            jq -r .name "$CONF_FILE"
            ;;
        yaml)
            yq -r '.services[].container_name' "$CONF_FILE"
            ;;
        cmd)
            ;;
        *)
            echo Unknown type: "$TYPE"
            exit 1
            ;;
    esac
}

start_(){
    image_ready=1
    for image in $(image_required)
    do
        if pull $image;then
            if [ "$image" != "$image_target" ];then
                image_update "$image" "$image_target"
            fi
        else
            image_ready=0
            break
        fi
    done

    if [ "$image_ready"n == 1n ];then
        echo Start install
        case "$TYPE" in
            json)
                container=$(jq -r .name "$CONF_FILE")
                curl_opt
                return_line=$($CURL -H "Content-type:application/json;charset='utf-8'" -H "Accept:application/json" -d @"$CONF_FILE" $url 2>/dev/null)
                if echo $return_line | jq -e .Id ;then
                    if [ "$START"n == 1n ];then
                        docker start "$container"
                    fi
                else
                    echo "$return_line" > $LAST_ERROR
                    chown www-data $LAST_ERROR
                    echo "$return_line" | grep .message
                fi
                ;;
            yaml)
                yq -i --yaml-output '.version |= tostring' "$CONF_FILE"
                if [ "$START"n == 1n ];then
                    return_line=$(docker compose -f "$CONF_FILE" --project-directory "$WORK_DIR" --compatibility up -d 2>&1)
                else
                    return_line=$(docker compose -f "$CONF_FILE" --project-directory "$WORK_DIR" --compatibility up --no-start 2>&1)
                fi
                if [ $? -ne 0 ];then
                    echo "$return_line" > $LAST_ERROR
                    chown www-data $LAST_ERROR
                fi
                ;;
            cmd)
                ;;
            *)
                echo Unknown type: "$TYPE"
                exit 1
                ;;
        esac
    else
        echo Pull image failed
    fi
}

clear_(){
    echo Clear tmp files
    rm -rf $JOB_DIR >/dev/null 2>&1 || :
}

case "$action" in
    start)
        prepare_
        start_
        ;;
    clear)
        clear_
        ;;
    *)
        ;;
esac

exit 0
