#!/usr/bin/env bash
. $GVM_ROOT/scripts/functions

function show_usage() {
	echo "Usage: gvm install [version] [options]"
	echo "    -s,  --source=SOURCE      Install Go from specified source."
	echo "    -n,  --name=NAME          Override the default name for this version."
	echo "    -pb, --with-protobuf      Install Go protocol buffers."
	echo "    -b,  --with-build-tools   Install package build tools."
	echo "    -h,  --help               Display this message."
}

read_command_line() {
	VERSION=$1
	if [[ "${VERSION:0:1}" != "-" ]]; then
		shift
	else
		display_warning "Invalid version: $1"
		show_usage
		exit 1
	fi
	GO_SOURCE_URL=https://go.googlecode.com/hg/
	for i in $*; do
		case $i in
			-s=*|--source=*)
				GO_SOURCE_URL=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
			;;
			-n=*|--name=*)
				GO_NAME=`echo $i | sed 's/[-a-zA-Z0-9]*=//'`
			;;
			-pb|--with-protobuf)
				INSTALL_PB="true"
			;;
			-b|--with-build-tools)
				INSTALL_BUILD_TOOLS="true"
			;;
			-h|--help)
				show_usage
				exit 0
			;;
			*)
				display_warning "Invalid option $i"
				show_usage
				exit 65 # Bad arguments
			;;
		esac
	done
}

download_source() {
	GO_CACHE_PATH=$GVM_ROOT/archive/go
	[[ -d $GO_CACHE_PATH ]] && return
	display_message "Downloading Go source..."
	hg clone $GO_SOURCE_URL $GO_CACHE_PATH >> $GVM_ROOT/logs/go-download.log  2>&1 ||
		display_fatal "Couldn't download Go source"
}

check_tag() {
	version=`hg tags -R $GO_CACHE_PATH | awk '{print $1}' | $SORT_PATH | $GREP_PATH "$VERSION" | $HEAD_PATH -n 1 | $GREP_PATH "$VERSION"`
}

update_source() {
	display_message "Updating Go source..."
	hg pull -R $GO_CACHE_PATH >> $GVM_ROOT/logs/go-download.log 2>&1 || 
		display_fatal "Couldn't get latest Go version info"
}

copy_source() {
	hg clone -u $version $GO_CACHE_PATH $GO_INSTALL_ROOT >> $GVM_ROOT/logs/go-$GO_NAME-install.log 2>&1 ||
		display_fatal "Couldn't copy source to target folder"
}


compile_go() {
	display_message " * Compiling..."
	unset GOARCH && unset GOOS && unset GOPATH && unset GOBIN && unset GOROOT &&
	export GOBIN=$GO_INSTALL_ROOT/bin && 
	export PATH=$GOBIN:$PATH && 
	export GOROOT=$GO_INSTALL_ROOT &&
	#cd $GO_INSTALL_ROOT/src && ./all.bash &> $GVM_ROOT/logs/go-$GO_NAME-compile.log || 
	cd $GO_INSTALL_ROOT/src && ./make.bash &> $GVM_ROOT/logs/go-$GO_NAME-compile.log || 
		(rm -rf $GO_INSTALL_ROOT && display_fatal "Failed to compile")
}

create_enviroment() {
	new_env_file=$GVM_ROOT/environments/$GO_NAME
	echo "export GVM_ROOT; GVM_ROOT=\"$GVM_ROOT\"" > $new_env_file
	echo "export gvm_go_name; gvm_go_name=\"$GO_NAME\"" >> $new_env_file
	echo "export gvm_pkgset_name; gvm_pkgset_name=\"global\"" >> $new_env_file
	echo "export GOROOT; GOROOT=\"\$GVM_ROOT/gos/$GO_NAME\"" >> $new_env_file
	echo "export GOPATH; GOPATH=\"\$GVM_ROOT/pkgsets/$GO_NAME/global\"" >> $new_env_file
	echo "export PATH; PATH=\"\$GVM_ROOT/pkgsets/$GO_NAME/global/bin:\$GVM_ROOT/gos/$GO_NAME/bin:\$GVM_ROOT/bin:\$PATH\"" >> $new_env_file
	. $GVM_ROOT/scripts/env/use
	gvm_use $GO_NAME &> /dev/null ||
		display_fatal "Failed to use installed version"
	gvm pkgset create global
	unset GOPATH
}

install_go() {
	GO_INSTALL_ROOT=$GVM_ROOT/gos/$GO_NAME
	trap 'rm -rf $GO_INSTALL_ROOT; display_fatal "Canceled!"' INT

	# Check for existing install
	if [[ -d "$GO_INSTALL_ROOT" ]]; then
		[[ -f "$GO_INSTALL_ROOT/manifest" ]] &&
			display_fatal "Already installed!"
		display_warning "Removing corrupt install..."
		gvm uninstall $GO_NAME
	fi

	if [[ "$version" != "$GO_NAME" ]]; then
		display_message "Installing $version as $GO_NAME..."
	else	
		display_message "Installing $version..."
	fi

	# Create the global package set folder
	mkdir -p $GVM_ROOT/pkgsets/$GO_NAME >> $GVM_ROOT/logs/go-$GO_NAME-install.log 2>&1 || 
		display_fatal "Couldn't create global package set folder"

	copy_source
	compile_go
	create_enviroment
}

install_gpkg() {
	display_message " * Installing gpkg..."
	$GVM_GOINSTALL github.com/moovweb/gpkg > $GVM_ROOT/logs/$GO_NAME-gpkg.log 2>&1 || return 1
}

install_gb() {
	display_message " * Installing gb..."
	$GVM_GOINSTALL github.com/jbussdieker/go-gb/gb > $GVM_ROOT/logs/$GO_NAME-gb.log 2>&1 || return 1
}

install_goprotobuf() {
	which protoc &> /dev/null || display_warning "Could not find protocol buffer compiler

  linux: apt-get install protobuf-compiler
  mac:   brew install protobuf
"
	display_message " * Installing goprotobuf..."
	if [[ "$GVM_GOINSTALL" == "goinstall" ]]; then
		$GVM_GOINSTALL goprotobuf.googlecode.com/hg/proto > $GVM_ROOT/logs/$GO_NAME-pb-compiler.log 2>&1
		if [[ $? -ne 0 ]]; then
			display_warning "Failed to install goprotobuf"
			return 1
		fi
		cd $GVM_ROOT/gos/$GO_NAME/src/pkg/goprotobuf.googlecode.com/hg/compiler
		make install >> $GVM_ROOT/logs/$GO_NAME-pb-compiler.log 2>&1
		if [[ $? -ne 0 ]]; then
			display_warning "Failed to install goprotobuf compiler"
			return 1
		fi
	else
		$GVM_GOINSTALL code.google.com/p/goprotobuf/proto > $GVM_ROOT/logs/$GO_NAME-pb-compiler.log 2>&1
		if [[ $? -ne 0 ]]; then
			display_warning "Failed to install goprotobuf"
			return 1
		fi
		$GVM_GOINSTALL code.google.com/p/goprotobuf/protoc-gen-go > $GVM_ROOT/logs/$GO_NAME-pb-compiler.log 2>&1
		if [[ $? -ne 0 ]]; then
			display_warning "Failed to install goprotobuf compiler"
			return 1
		fi
	fi
}

main() {
	trap 'display_fatal "Canceled!"' INT
	read_command_line $@
	[[ "$VERSION" == "" ]] && display_fatal "No version specified"
	download_source
	check_tag || (update_source && check_tag) || display_fatal "Unrecognized Go version"
	if [[ "$GO_NAME" == "" ]]; then
		GO_NAME=$version
	fi
	install_go

	GVM_GOINSTALL="goinstall"
	which goinstall &> /dev/null ||
		GVM_GOINSTALL="go get"

	x="`hg tags -R ~/.gvm/archive/go`"; echo ${x#*b0819469a6df} | $GREP_PATH "$version " &> /dev/null
	if [[ "$?" == "1" ]]; then
		if [[ "$INSTALL_BUILD_TOOLS" == "true" ]]; then
			install_gb || display_warning "Failed to install gb"
			install_gpkg || display_warning "Failed to install gpkg"
		fi
		if [[ "$INSTALL_PB" == "true" ]]; then
			install_goprotobuf
		fi
	fi

	cd $GO_INSTALL_ROOT && find . > manifest
}

main $@

