#!/bin/bash -e

CURRENTDIR=$(pwd)

#------------------------------------------------------------------------------------------
function usage() {
  cat <<EOF

Run the simulations in a docker container for playing around

OPTIONS:
  -h, --help                          Show this message

Container OPTIONS:
  --shell                             Start the shell within the simulation container
  --delete-container                  Delete container before starting
  --container-name [NAME]             Append the given name to the default container name based on the system type for keeping builds separate if required.

EOF
}

# bash colors
BASH_GREEN="\e[1;32m"
BASH_RED="\e[1;31m"
BASH_YELLOW="\e[0;33m"
BASH_NORMAL="\e[0m"
COLORS=true

#------------------------------------------------------------------------------------------
function printGreen() {
    if ${COLORS}; then
        echo -e "${BASH_GREEN}[+] $1${BASH_NORMAL}"
    else
        echo -e "[+] $1"
    fi
}

#------------------------------------------------------------------------------------------
function printYellow() {
    if ${COLORS}; then
        echo -e "${BASH_YELLOW}[+] $1${BASH_NORMAL}"
    else
        echo -e "[+] $1"
    fi
}


#------------------------------------------------------------------------------------------
function printRed() {
    if ${COLORS}; then
        echo -e "${BASH_RED}[!] $1${BASH_NORMAL}"
    else
        echo -e "[!] $1"
    fi
}


#------------------------------------------------------------------------------------------

function buildImage() {
    printGreen "Build image ${IMAGE_NAME} "
    docker build -t ${IMAGE_NAME} -f- . <<EOF
        FROM debian:${DEBIAN_RELEASE}

        ENV DEBIAN_FRONTEND noninteractive
        ENV container docker
        ENV LC_ALL C

        RUN apt-get -y update
        RUN apt-get -y install nano wget

        RUN echo "deb http://repository.nymea.io/experimental ${DEBIAN_RELEASE} main" > /etc/apt/sources.list.d/nymea.list
        RUN wget -O /etc/apt/trusted.gpg.d/nymea.gpg https://repository.nymea.io/nymea.gpg

        RUN apt-get -y update
        RUN apt-get -y install  libnymea-dev libnymea-core-dev libnymea-tests-dev libnymea-energy-dev \
                                nymea-experience-plugin-energy libqt5websockets5-dev nymea-dev-tools:native \
                                qt5-qmake qtbase5-dev gnuplot build-essential

        RUN apt-get -y clean
        RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

        RUN echo "alias ll='ls -la'" >> /etc/bash.bashrc

        RUN mkdir /nymea-energy/
        RUN mkdir /nymea-energy-source/

        # Create the ssh entry point in order to have the correct ssh file within the container
        # and start sleeping infinite. We want the container to run so we can start commands from the host
        RUN echo '#!/bin/bash -e' > /bin/docker-entrypoint.sh && \
            echo '' >> /bin/docker-entrypoint.sh && \
            echo 'sleep infinity' >> /bin/docker-entrypoint.sh

        RUN chmod +x /bin/docker-entrypoint.sh

        ENTRYPOINT ["/bin/docker-entrypoint.sh"]

        WORKDIR /nymea-energy/
EOF
}

function startContainer() {
    printGreen "Starting container ${CONTAINER_NAME}"
    docker start ${CONTAINER_NAME}
}

function executeContainer() {
    COMMAND="$@"
    set +e
    docker exec -w /nymea-energy -u root --privileged ${CONTAINER_NAME} /bin/bash -e -o pipefail -c "$COMMAND"
    BUILD_RESULT=$?
    set -e
    if [ ${BUILD_RESULT} -ne 0 ]; then
        printRed "Build command finished with error. Keeping the container for inspection."
        exit 1
    fi
}

function launchContainer() {
    printGreen "Creating container ${CONTAINER_NAME} from ${IMAGE_NAME}"
    docker run -d --name "${CONTAINER_NAME}" --privileged \
		--cap-add=ALL \
		--volume /dev:/dev \
        --volume /sys/fs/cgroup:/sys/fs/cgroup:ro \
        --volume ${CURRENTDIR}:/nymea-energy-source/:ro \
        ${IMAGE_NAME}
}

function synchSourceInContainer() {
    printGreen "Synchronize source in the container ..."
    executeContainer "rsync -rlptD --delete --exclude 'build' --exclude 'output' /nymea-energy-source/ ."
    executeContainer "ls -la"
}

#------------------------------------------------------------------------------------------
# Main
#------------------------------------------------------------------------------------------

KEEP_DATA=false
KEEP_CONTAINER=true
RUN_SHELL=false
RUN_DELETE_CONTAINER=false
CONTAINER_NAME_APPEND=""

DEBIAN_RELEASE=bookworm

while [ "$1" != "" ]; do
    case $1 in
        --delete-container )
            RUN_DELETE_CONTAINER=true;;
        --shell )
            RUN_SHELL=true;;
        --container-name )
            CONTAINER_NAME_APPEND=$2
            shift;;
        -h | --help )
            usage && exit 0;;
        * )
            usage && exit 1;;
    esac
    shift
done

if ! docker ps >/dev/null; then
    printRed "Error connecting to docker:"
    docker ps
    exit 1
fi

IMAGE_NAME=nymea-energy
CONTAINER_NAME=${IMAGE_NAME}-simulation
if [ ! -z ${CONTAINER_NAME_APPEND} ]; then
    CONTAINER_NAME=${IMAGE_NAME}-${CONTAINER_NAME_APPEND}-simulation
fi

# Verify image
IMAGE_EXISTS=false
if docker image ls | grep ${IMAGE_NAME} >/dev/null; then
    printGreen "--> Image ${IMAGE_NAME} already created on this host."
    IMAGE_EXISTS=true
else
    printGreen "--> Image ${IMAGE_NAME} not found. Creating image first..."
    buildImage
fi

# Verify container exists
CONTAINER_EXISTS=false
if [ "$(docker ps -a --filter name="${CONTAINER_NAME}" -q)" != "" ]; then
    printGreen "--> Container ${IMAGE_NAME} exists"
    CONTAINER_EXISTS=true
else
    printGreen "--> Container ${IMAGE_NAME} does not exist yet."
fi

# Verify container running
CONTAINER_RUNNING=false
if [ "$(docker ps --filter name="${CONTAINER_NAME}" -q)" != "" ]; then
    printGreen "--> Container ${IMAGE_NAME} is up and running."
    CONTAINER_RUNNING=true
else
    printGreen "--> Container ${IMAGE_NAME} is not running."
fi

# Handle delete container request
if ${RUN_DELETE_CONTAINER}; then
    if ${CONTAINER_EXISTS}; then
        printGreen "Delete container ${CONTAINER_NAME}"
        docker rm -fv "${CONTAINER_NAME}"
        CONTAINER_RUNNING=false
        CONTAINER_EXISTS=false
    fi
fi

# Handle shell login into container
if ${RUN_SHELL}; then
    if ${CONTAINER_EXISTS}; then
        if ! ${CONTAINER_RUNNING}; then
            startContainer
        fi
    else
        launchContainer
        synchSourceInContainer
    fi

    docker exec -it -w /nymea-energy -u root --privileged ${CONTAINER_NAME} /bin/bash
    exit 0
fi


if ${CONTAINER_RUNNING}; then
    printYellow "The simulation container ${CONTAINER_NAME} is running. Stopping it..."
    docker stop ${CONTAINER_NAME}
fi


BUILD_COMMAND='if [ ! -d build ]; then mkdir -p build; fi ; cd build ; qmake .. ; make -j $(nproc) ; cd ./tests/auto/simulation/ ; pwd; ./nymea-energy-simulation -maxwarnings 0'
printGreen "Running build script with"
echo "${BUILD_COMMAND}"

# Run the build command inside the container
if ${CONTAINER_EXISTS}; then
    startContainer
    synchSourceInContainer
    executeContainer "${BUILD_COMMAND}"
else
    launchContainer
    synchSourceInContainer
    executeContainer "${BUILD_COMMAND}"
fi

printGreen "Copy simulation results from container..."
RESULTS_DIR=${CURRENTDIR}/results
if [ -d ${RESULTS_DIR} ]; then
    printGreen "Clean up previouse results ..."
    rm -rf ${RESULTS_DIR}
fi
mkdir -p ${RESULTS_DIR}
docker cp ${CONTAINER_NAME}:/nymea-energy/build/tests/auto/simulation/simulations/results/ ${CURRENTDIR}

printGreen "Stopping the container"
docker stop ${CONTAINER_NAME}

# Cleanup if required
if ! $KEEP_CONTAINER; then
    printGreen "Delete container ${CONTAINER_NAME}"
    docker rm -v "${CONTAINER_NAME}"
fi

printGreen "Simulation run finished successfully. Results can be found in ${RESULTS_DIR}"
ls -l ${RESULTS_DIR}
