#!/usr/bin/env bash
#
# Mini Object Storage, (C) 2015 Minio, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

_init() {
    ## Minimum required versions for build dependencies
    GCC_VERSION="4.0"
    CLANG_VERSION="3.5"
    YASM_VERSION="1.2.0"
    GIT_VERSION="1.0"
    GO_VERSION="1.4"
    OSX_VERSION="10.8"
    UNAME=$(uname -sm)

    ## Check all dependencies are present
    MISSING=""
}

###
#
# Takes two arguments
# arg1: version number in `x.x.x` format
# arg2: version number in `x.x.x` format
#
# example: check_version "$version1" "$version2"
#
# returns:
# 0 - Installed version is equal to required
# 1 - Installed version is greater than required
# 2 - Installed version is lesser than required
# 3 - If args have length zero
#
####
check_version () {
    ## validate args
    [[ -z "$1" ]] && return 3
    [[ -z "$2" ]] && return 3

    if [[ $1 == $2 ]]; then
        return 0
    fi

    local IFS=.
    local i ver1=($1) ver2=($2)
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)); do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++)); do
        if [[ -z ${ver2[i]} ]]; then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        if ((10#${ver1[i]} > 10#${ver2[i]})); then

            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]})); then
	    ## Installed version is lesser than required - Bad condition
            return 2
        fi
    done
    return 0
}

check_golang_env() {
    echo ${GOROOT:?} 2>&1 >/dev/null
    if [ $? -eq 1 ]; then
	echo "ERROR"
	echo "GOROOT environment variable missing, please refer to Go installation document"
	echo "https://github.com/Minio-io/minio/blob/master/BUILDDEPS.md#install-go-13"
	exit 1
    fi

    echo ${GOPATH:?} 2>&1 >/dev/null
    if [ $? -eq 1 ]; then
	echo "ERROR"
	echo "GOPATH environment variable missing, please refer to Go installation document"
	echo "https://github.com/Minio-io/minio/blob/master/BUILDDEPS.md#install-go-13"
	exit 1
    fi
}

is_supported_os() {
    case ${UNAME%% *} in
        "Linux")
            os="linux"
            ;;
	"Darwin")
	    osx_host_version=$(env sw_vers -productVersion)
	    check_version "${osx_host_version}" "${OSX_VERSION}"
	    [[ $? -ge 2 ]] && die "Minimum OSX version supported is ${OSX_VERSION}"
	    ;;
	"*")
	    echo "Exiting.. unsupported operating system found"
	    exit 1;
    esac
}

is_supported_arch() {
    local supported
    case ${UNAME##* } in
        "x86_64")
            supported=1
            ;;
        *)
            supported=0
            ;;
    esac
    if [ $supported -eq 0 ]; then
        echo "Invalid arch: ${UNAME} not supported, please use x86_64/amd64"
	exit 1;
    fi
}

check_deps() {
    check_version "$(env go version 2>/dev/null | sed 's/^.* go\([0-9.]*\).*$/\1/')" "${GO_VERSION}"
    if [ $? -ge 2 ]; then
	MISSING="${MISSING} golang(1.4)"
    fi

    check_version "$(env git --version 2>/dev/null | sed -e 's/^.* \([0-9.\].*\).*$/\1/' -e 's/^\([0-9.\]*\).*/\1/g')" "${GIT_VERSION}"
    if [ $? -ge 2 ]; then
	MISSING="${MISSING} git"
    fi

    case ${UNAME%% *} in
        "Linux")
	    check_version "$(env gcc --version 2>/dev/null | sed 's/^.* \([0-9.]*\).*$/\1/' | head -1)" "${GCC_VERSION}"
	    if [ $? -ge 2 ]; then
		MISSING="${MISSING} build-essential"
	    fi
            ;;
	"Darwin")
	    check_version "$(env gcc --version 2>/dev/null | sed 's/^.* \([0-9.]*\).*$/\1/' | head -1)" "${CLANG_VERSION}"
	    if [ $? -ge 2 ]; then
		MISSING="${MISSING} xcode-cli"
	    fi
	    ;;
	"*")
	    ;;
    esac

    check_version "$(env yasm --version 2>/dev/null | sed 's/^.* \([0-9.]*\).*$/\1/' | head -1)" "${YASM_VERSION}"
    if [ $? -ge 2 ]; then
	MISSING="${MISSING} yasm(1.2.0)"
    fi

    env mkdocs help >/dev/null 2>&1
    if [ $? -ne 0 ]; then
	MISSING="${MISSING} mkdocs"
    fi
}

main() {
    echo -n "Check for supported arch.. "
    is_supported_arch

    echo -n "Check for supported os.. "
    is_supported_os

    echo -n "Checking if proper environment variables are set.. "
    check_golang_env

    echo "Done"
    echo "Using GOPATH=${GOPATH} and GOROOT=${GOROOT}"

    echo -n "Checking dependencies for Minio.. "
    check_deps

    ## If dependencies are missing, warn the user and abort
    if [ "x${MISSING}" != "x" ]; then
	echo "ERROR"
	echo
	echo "The following build tools are missing:"
	echo
	echo "** ${MISSING} **"
	echo
	echo "Please install them "
	echo "${MISSING}"
	echo
	echo "Follow https://github.com/Minio-io/minio/blob/master/BUILDDEPS.md for further instructions"
	exit 1
    fi
    echo "Done"
}

_init && main "$@"