#!/bin/bash

DEFAULT_OPENSHIFT_VERSION="v3.11.0"
DEFAULT_CPUS="2"
DEFAULT_DISK_SIZE="20GB"
DEFAULT_RAM="4912"
ADMIN_USER="system:admin"

minishift::description() {
    echo "Initialize and manage a Minishift developer environment"
}

minishift::usage() {
    cat <<EOT
    --install                 Install to a running Minishift.
    --app-options             Operator parameters when installing the app.
                              Use quotes and start with a space before appending the options (example: " --addons jaeger").
-p  --project                 Install into this project. Delete this project if it already exists.
                              By default, install into the current project (without deleting)
    --profile <profile>       Use the given minishift profile
    --reset                   Reset and initialize the minishift installation by
                              'minishift delete && minishift start'.
    --full-reset              Full reset and initialie by
                              'minishift stop && rm -rf ~/.minishift/* && minishift start'
    --operator-only           Only install the operator but no custom resource
    --memory <mem>            How much memory to use when doing a reset. Default: $DEFAULT_RAM
    --cpus <nr cpus>          How many CPUs to use when doing a reset. Default: $DEFAULT_CPUS
    --disk-size <size>        How many disk space to use when doing a reset. Default: $DEFAULT_DISK_SIZE
    --vm-driver <driver>      Which virtual machine driver to use (depends on OS)
    --show-logs               Show minishift logs during startup
    --openshift-version <ver> Set OpenShift version to use when reseting (default: $DEFAULT_OPENSHIFT_VERSION)
    --tag <tag>               Syndesis version/tag to install. If not given, then the latest
                              version is installed
-f  --force-binary-download   By default if the binary cli is present in the expected path, it will
                              be used. With this option enabled, the binary will be removed and downloaded,
                              ensuring it is the latest version
-o  --open                    Open Syndesis in the browser
-y  --yes                     Assume 'yes' automatically when asking for deleting
                              a given project.
    --maven-mirror            Install Maven Mirror to be used with --maven-mirror when building.
    --deploy-latest           Deploy latest tags from dockerhub.
    --nodev                   Do not set the devSupport flag in CR (deploys all images)
    --custom-resource         Provide a custom resource to be installed by the operator
EOT
}


minishift::run() {
    source "$(basedir)/commands/util/openshift_funcs"
    source "$(basedir)/commands/util/operator_funcs"

    release_tag="$(readopt --tag)"
    if [[ $(hasflag -f --force-binary-download) ]] || [[ -n "$release_tag" ]]; then
        if [[ -f ${OPERATOR_BINARY} ]]; then
            rm ${OPERATOR_BINARY}
        fi
    fi
    download_operator_binary || print_error_and_exit "unable to download the operator binary, exit"

    # Check that minishift is installed
    which minishift &>/dev/null
    if [ $? -ne 0 ]; then
        echo "ERROR: No 'minishift' found in path."
        echo "Please install Minishift from https://github.com/MiniShift/minishift"
        exit 1
    fi

    local profile=$(readopt --profile)
    if [ -n "${profile}" ]; then
        # Switch to profile
        echo "Using profile $profile"
        minishift profile set $profile
    fi

    if [ $(hasflag --full-reset) ] || [ $(hasflag --reset) ]; then
        delete_minishift $(hasflag --full-reset)
        start_minishift
    fi

    # Start minishift if necessary
    if [ -z "$(is_minishift_running)" ]; then
        start_minishift
    fi

    # Ensure OC is in the path
    eval $(minishift oc-env --shell bash)

    if [ $(hasflag --maven-mirror) ]; then
        install_maven_mirror
    fi

    if [ $(hasflag --install) ]; then

        # syndesis-operator install --help prints the version in the --tag description
        operator_version=$($OPERATOR_BINARY install --help|grep '\-\-tag'|cut -d "\"" -f 2)
        echo "Syndesis version: ${operator_version}"

        # Switch to the proper context
        local profile=$(readopt --profile)
        if [ -n "${profile}" ]; then
          # Switch to context
          echo "Using context/profile $context"
          oc config use-context $context
        fi

        #Check the custom resource if one has been specified
        local customcr=$(readopt --custom-resource)
        if [ -n "${customcr}" ]; then
            if [ ! -f "${customcr}" ]; then
                check_error "ERROR: No custom resource exists at '${customcr}'"
            fi
        fi

        # Pick the proper project
        local original_project="$(oc project -q)"
        local project=$(readopt --project -p)
        if [ -n "${project}" ]; then
            recreate_project $project "$(hasflag --yes -y)"
        else
            local project="$original_project"
        fi

        # Adapt namespace of profile to the selected
        # project if a profile is used
        if [ -n "$profile" ]; then
            oc config set-context "$profile" --namespace="$project"
        fi

        echo "Switching to project \"$project\""
        oc project $project

        # Login as admin to install CRDs
        local user=$(oc whoami)
        local revert_login=$(login_as_admin)

        # Install Syndesis CRD globally (if required)
        if ! $(oc get crd | grep "syndesises.syndesis.io" >/dev/null 2>&1); then
            echo "Installing Syndesis CRD"
            local result=$($OPERATOR_BINARY install cluster)
            check_error "$result"
        fi

        if [[ "$ADMIN_USER" != "$user" ]]; then
            echo "Grant user $user permissions"
            local result=$($OPERATOR_BINARY grant --user $user)
            check_error "$result"
        fi

        # Revert back to the original user whose been granted install rights
        $revert_login

        # Deploy operator
        echo "Deploying Syndesis operator"
        if [ $(hasflag --nodev) ] ; then
            result=$($OPERATOR_BINARY install operator)
        else
            result=$($OPERATOR_BINARY install operator --dev)
            echo "To complete the installation please go ahead and run local dev builds for syndesis-server syndesis-ui syndesis-meta syndesis-s2i."
        fi
        check_error "$result"

        wait_for_deployments 1 syndesis-operator

        # Relogin with original user
        echo "Switching to project \"$project\""
        oc project $project >/dev/null 2>&1

        local app_options=$(readopt --app-options)
        if [ $(hasflag --operator-only) ]; then
            echo "Deployed operator."
            exit 0
        else
            # Deploying syndesis app
            local customcr=$(readopt --custom-resource)

            if [ -n "${customcr}" ]; then
                echo "Deploying syndesis app with custom resource ${customcr}"
                app_options=$app_options" --custom-resource ${customcr}"
            else
                echo "Deploying syndesis app."
            fi

            result=$($OPERATOR_BINARY install app $app_options)
            check_error "$result"
        fi

        echo "Install finished."
    fi

    if [ $(hasflag --open -o) ]; then
        while ! (oc get routes | grep syndesis >/dev/null 2>&1); do
            echo "Sleeping 5s ..."
            sleep 5
        done
        open_url "https://$(oc get routes syndesis --template "{{.spec.host}}")"
    fi

    if [ $(hasflag --deploy-latest) ]; then
        deploy_latest
    fi
}

login_as_admin() {
    local user=$(oc whoami)
    local token=$(extract_current_token)
    local project=$(oc project -q)

    # Login in as admin
    oc login -u "$ADMIN_USER" >/dev/null 2>&1

    # Return the command to use to revert to the initial user
    if [ -n "${token}" ]; then
        echo "oc login -u ${user} -p $token"
    else
        echo "oc login -u ${user}"
    fi
}

extract_current_token() {
    local token=$(oc whoami -t 2>/dev/null)
    if [ $? == 0 ]; then
        echo $token
    fi
}

is_minishift_running() {
    set +e
    minishift status 2>&1 | grep -q "Running"
    local stat=$?
    set -e
    if [ $stat -eq 0 ]; then
      echo "true"
    fi
}

delete_minishift() {
    local remove_all=${1:-}

    if [ $(is_minishift_running) ]; then
      minishift stop
    fi

    minishift delete --clear-cache --force
    if [ $remove_all ] && [ -d ~/.minishift ]; then
        rm -rf ~/.minishift/*
    fi
}

start_minishift() {
    local memory=$(readopt --memory)
    local cpus=$(readopt --cpus)
    local disksize=$(readopt --disk-size)
    local openshift_version=$(readopt --openshift-version)
    local extra_args=""
    if [ $(hasflag --show-logs --show-log) ]; then
        extra_args="--show-libmachine-logs=true "
    fi
    local vmdriver=$(readopt --vm-driver --vmdriver)
    if [ -n "${vmdriver}" ]; then
        extra_args="${extra_args}--vm-driver ${vmdriver} "
    fi

    minishift addons enable admin-user

    echo "Starting minishift ...."
    minishift start ${extra_args:-}\
            --memory ${memory:-$DEFAULT_RAM} \
            --cpus ${cpus:-$DEFAULT_CPUS} \
            --disk-size ${disksize:-$DEFAULT_DISK_SIZE} \
            --openshift-version ${openshift_version:-$DEFAULT_OPENSHIFT_VERSION}
}

deploy_latest() {
    DOCKER_IMAGES="syndesis-meta syndesis-s2i syndesis-server syndesis-ui"
    eval $(minishift docker-env)
    docker login -u $(oc whoami) -p $(oc whoami -t) $(minishift openshift registry) >/dev/null 2>&1
    for image in ${DOCKER_IMAGES}; do
      docker pull syndesis/${image}
      docker tag syndesis/${image} $(minishift openshift registry)/syndesis/${image}
      docker push $(minishift openshift registry)/syndesis/${image}
    done
    docker logout $(minishift openshift registry) >/dev/null 2>&1
    eval $(minishift docker-env -u)
}
