#!/bin/bash -e

PROGRAM_NAME=`basename $0`

display_help () {
    echo "Usage: $PROGRAM_NAME [options] [command]"
    echo ""
    echo "Available commands:"
    echo "    help                - Display this help."
    echo "    delete              - Delete a container."
    echo "    shell               - Enter a container."
    echo "    clean               - Clean the snap build dir."
    echo "Options:"
    echo "    --help, -h          - Display this help."
    echo "    --mount-ssh         - Mount ~/.ssh into the container (if snapcraft requires ssh keys to access repositories)."
    echo "    --silo, -s          - Add ci-repo.nymea.io/... to the apt sources"
    echo "  --container-prefix    - LXD container prefix to use"
}

# Default variables, may be overriden by command line args
defaults () {
    SNAPCRAFT_FILE=snapcraft.yaml
    MOUNT_SSH=0
}

# Setup the entire env after having parsed command line args
variables () {

    if [ ! -e $SNAPCRAFT_FILE ]; then
        if [ ! -d snap ]; then
            echo "${NEGATIVE_COLOR}snapcraft.yaml not found.${NC}"
            exit 1
        else
            SNAPCRAFT_FILE=snap/snapcraft.yaml
            if [ ! -e $SNAPCRAFT_FILE ]; then
                echo "${NEGATIVE_COLOR}snap/snapcraft.yaml not found.${NC}"
                exit 1
            fi
        fi

    fi

    if grep "base: core18" $SNAPCRAFT_FILE > /dev/null; then
        DISTRO=bionic
    else
        DISTRO=xenial
    fi
    PACKAGE=`cat $SNAPCRAFT_FILE | grep name | head -n 1 | cut -d " " -f 2`
    VERSION=`cat $SNAPCRAFT_FILE | grep version | head -n 1 | cut -d " " -f 2`
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    LIGHT_RED='\033[1;31m'
    LIGHT_GREEN='\033[1;32m'
    NC='\033[0m'
    ERROR_COLOR=$LIGHT_RED
    POSITIVE_COLOR=$GREEN

    HOST_ARCH=`dpkg --print-architecture`
    LXD_IMAGE_NAME=nymea-snap-builder-$DISTRO-$HOST_ARCH
    LXD_IMAGE=nymea:$LXD_IMAGE_NAME
    LXD_CONTAINER=builder-$PACKAGE-$LXD_IMAGE_NAME
    if [ ! -z $CONTAINER_PREFIX ]; then
        LXD_CONTAINER=$CONTAINER_PREFIX-$LXD_CONTAINER
    fi
    if stat --file-system $HOME | grep ecrypt ; then
        ENCRYPTED_HOME=1
    fi
    USERNAME=`id --user --name`
    GROUPNAME=$USERNAME
#    if [ -n "$ENCRYPTED_HOME" ] ; then
        USERID=`id --user`
        GROUPID=`id --group`
#    else
#        USERID=150000
#        GROUPID=150000
#    fi
    MOUNTED_DIRECTORY=$PWD
    USERDIR=~
    MOUNT_POINT=$USERDIR/$PACKAGE
    SOURCE_PATH_CONTAINER=$MOUNT_POINT
}


new_container () {
    # setup the building container
    if lxc info $LXD_CONTAINER > /dev/null 2>&1 ; then
        echo "${POSITIVE_COLOR}LXD container $LXD_CONTAINER already exists.${NC}"
        # FIXME: check if the container is already started
        lxc start $LXD_CONTAINER || true
    else
        echo "${POSITIVE_COLOR}Creating LXD container $LXD_CONTAINER using $LXD_IMAGE.${NC}"
        lxc remote --public=true --accept-certificate=true add nymea https://jenkins.nymea.io || true
#        lxc remote --protocol=simplestreams --public=true --accept-certificate=true add sdk https://sdk-images.canonical.com || true
        lxc init $LXD_IMAGE $LXD_CONTAINER
        lxc config set $LXD_CONTAINER security.nesting true
        lxc config set $LXD_CONTAINER security.privileged true

        lxc start $LXD_CONTAINER
        USERNAME_CONTAINER=`lxc exec $LXD_CONTAINER grep ":$USERID:" /etc/passwd | cut -f 1 -d ":"`
        if [ "$USERNAME_CONTAINER" != "" ]; then
            lxc exec --env GROUPID=$GROUPID --env GROUPNAME=$GROUPNAME $LXD_CONTAINER -- deluser $USERNAME_CONTAINER
        fi
        #lxc exec --env GROUPID=$GROUPID --env GROUPNAME=$GROUPNAME $LXD_CONTAINER -- delgroup $USERNAME_CONTAINER
        lxc exec --env GROUPID=$GROUPID --env GROUPNAME=$GROUPNAME $LXD_CONTAINER -- addgroup --gid $GROUPID $GROUPNAME
        lxc exec --env GROUPID=$GROUPID --env USERNAME=$USERNAME --env USERID=$USERID $LXD_CONTAINER -- adduser --disabled-password --gecos "" --uid $USERID --gid $GROUPID $USERNAME
#        lxc exec --env USERNAME=$USERNAME $LXD_CONTAINER -- usermod -aG sudo $USERNAME
        exec_container_root "sed -i 's/ENV_PATH.*PATH=/ENV_PATH\tPATH=\/usr\/lib\/ccache:/' /etc/login.defs"
        # wait for the container's network connection
        check_for_container_network
        enable_overlay_source
        exec_container_root rm /var/lib/dpkg/lock || true
        exec_container_root rm /var/lib/dpkg/lock-frontend || true
        exec_container_root apt-get update
        exec_container_root rm /var/lib/dpkg/lock || true
        exec_container_root rm /var/lib/dpkg/lock-frontend || true
        exec_container_root apt-get install -y sudo debhelper ccache software-properties-common devscripts snapcraft
        exec_container_root adduser $USERNAME sudo
        # set empty password for the user
        exec_container_root passwd --delete $USERNAME
    fi

    if ! lxc config device get $LXD_CONTAINER current_dir_mount disk 2> /dev/null ; then
        echo "${POSITIVE_COLOR}Mounting $MOUNTED_DIRECTORY in container.${NC}"
        lxc config device add $LXD_CONTAINER current_dir_mount disk source=$MOUNTED_DIRECTORY path=$MOUNT_POINT
    else
        lxc config device set $LXD_CONTAINER current_dir_mount source $MOUNTED_DIRECTORY
    fi

    if ! lxc config device get $LXD_CONTAINER ccache_dir_mount disk 2> /dev/null ; then
        echo "${POSITIVE_COLOR}Mounting ccache dir ($HOME/.ccache) in container.${NC}"
        lxc config device add $LXD_CONTAINER ccache_dir_mount disk source=$HOME/.ccache/ path=$HOME/.ccache
    fi
    
    if [ $MOUNT_SSH -eq 1 ]; then
        if ! lxc config device get $LXD_CONTAINER ssh_dir_mount disk 2> /dev/null ; then
            echo "${POSITIVE_COLOR}Mounting ssh config dir ($HOME/.ssh) in container.${NC}"
            lxc config device add $LXD_CONTAINER ssh_dir_mount disk source=$HOME/.ssh/ path=$HOME/.ssh
        fi
    fi
}

delete_container () {
    echo "${POSITIVE_COLOR}Deleting LXD container $LXD_CONTAINER.${NC}"
    lxc delete -f $LXD_CONTAINER
}

shell_container () {
    echo "${POSITIVE_COLOR}Entering shell in LXD container $LXD_CONTAINER.${NC}"
    lxc exec $LXD_CONTAINER -- su --login $USERNAME
}

enable_overlay_source () {
    exec_container_root apt-key adv --keyserver keyserver.ubuntu.com --recv-key A1A19ED6
#    exec_container_root apt-add-repository \"deb http://repository.nymea.io $DISTRO main\"
#    exec_container_root cat /etc/apt/sources.list
    exec_container_root "echo deb http://repository.nymea.io $DISTRO main non-free > /etc/apt/sources.list.d/nymea.list"
    exec_container_root cat /etc/apt/sources.list.d/nymea.list
    if [ "$SILO_NAME" != "" ]; then
        exec_container_root "echo deb http://ci-repo.nymea.io/$SILO_NAME $DISTRO main non-free > /etc/apt/sources.list.d/nymea-silo.list"
        exec_container_root cat /etc/apt/sources.list.d/nymea-silo.list
    fi
}

check_command_parameter_count () {
    MIN_PARAMETERS=$1
    MAX_PARAMETERS=$2
    COUNT=$(echo $PARAMETERS | wc -w)
    if  [ -n $MIN_PARAMETERS ] && [ $COUNT -lt $MIN_PARAMETERS ] ; then
        display_help
        echo ""
        echo "${ERROR_COLOR}Command '$COMMAND' requires a minimum of $MIN_PARAMETERS parameters. $COUNT passed.${NC}"
        exit 1
    fi
    if [ -n $MAX_PARAMETERS ] && [ $COUNT -gt $MAX_PARAMETERS ] ; then
        display_help
        echo ""
        echo "${ERROR_COLOR}Command '$COMMAND' accepts at most $MAX_PARAMETERS parameters. $COUNT passed.${NC}"
        exit 1
    fi
}

exec_container_root () {
    command="$@"
    #echo lxc exec $LXD_CONTAINER "$@"
    lxc exec $LXD_CONTAINER -- sh -c "cd $SOURCE_PATH_CONTAINER; $command"
}

exec_container () {
    command="$@"
    #echo lxc exec $LXD_CONTAINER "$@"
    lxc exec $LXD_CONTAINER -- su -l -c "cd $SOURCE_PATH_CONTAINER; $command" $USERNAME
}

check_for_container_network() {
    NETWORK_UP=0
    for i in `seq 1 20`
    do
        if lxc info $LXD_CONTAINER | grep -e "eth0.*inet\b" > /dev/null 2>&1 ; then
            NETWORK_UP=1
            break
        fi
        sleep 1
    done
    if [ $NETWORK_UP -ne 1 ] ; then
        echo "${ERROR_COLOR}Container is not connected to the Internet.${NC}"
        exit 1
    fi
}

build () {
    exec_container_root rm /var/lib/dpkg/lock || true
    exec_container snapcraft
}

clean () {
    exec_container snapcraft clean $@
}

# Setup defaults before parsing command line
defaults

while [ "$1" != "" ]; do
    OPTION=`echo $1 | awk -F= '{print $1}'`
    VALUE=`echo $1 | awk -F= '{print $2}'`
    case $1 in
        -*)
            case $OPTION in
            --mount-ssh)
                MOUNT_SSH=1
            ;;
            --container-prefix)
                CONTAINER_PREFIX=$VALUE
            ;;
            --silo)
                SILO_NAME=$VALUE
            ;;
            -s)
                shift;
                SILO_NAME=$1
            ;;
            --help | -h | help )
                display_help
                exit 0
            ;;
            *)
                display_help
                echo ""
                echo "${ERROR_COLOR}error: unknown option: $OPTION${NC}"
                exit 1
            ;;
            esac
            shift
        ;;
        *)
            break
        ;;
    esac
done

# Now populate the complete environment
variables

COMMAND=$1
if [ -n "$COMMAND" ] ; then
    shift
fi

if [ "$COMMAND" = "help" ] ; then
    display_help
    exit 0
fi
if [ -z "$COMMAND" ] ; then
    new_container
    build
else
    PARAMETERS=$@
    case "$COMMAND" in
        delete)
            check_command_parameter_count 0 1
            delete_container
        ;;
        shell)
            check_command_parameter_count 0 1
            new_container
            shell_container
        ;;
        build)
            new_container
            build
        ;;
        clean)
            new_container
            clean $@
        ;;
        *)
            display_help
            echo ""
            echo "${ERROR_COLOR}error: unknown command: $COMMAND${NC}"
            exit 1
        ;;
    esac
fi
