#!/bin/bash

declare bash_shared_dir="../../../shared"


declare error=0
declare warn=10
declare info=20
declare verbose=30

declare -ra param_verbose=("verbose" "v" "" "Enable verbose logging")

declare log_level=$info

function log_usage()
{
	printf "%-5s %-20s %-70s %s$end_line" "-${param_verbose[1]}" "--${param_verbose[0]}" "${param_verbose[3]}" "${param_verbose[2]}"
}

function log_parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi

	 	case $1 in
	 		--${param_verbose[0]}|-${param_verbose[0]}|-${param_verbose[1]}|--${param_verbose[1]})
				log_level=$verbose
				shift 1
			;;
			*)
				shift 1
			;;
		esac
	done
}

function log_init()
{
	log_parse_command_line $@
}

function log()
{
	local level=$1
	local message=$2
	
	if [ "$level" -le "$log_level" ]; then
		
		level_str="INFO"
		color='\e[39m'
		clear_color='\E[00m'
		
		if [ $level -eq $warn ]; then
			level_str="WARN"
			color="\e[33m"
		elif [ $level -eq $error ]; then
			level_str="ERROR"
			color="\e[31m"
		fi
		
		if [ -t 1 ] ; then
			printf "$color%-6s$clear_color %s\n" "$level_str" "$message"
		else
			printf "%-6s %s\n" "$level_str" "$message"
		fi
	fi
}

function log_is_verbose()
{
	if [ "$verbose" -le "$log_level" ]; then
		return 0
	fi
	
	return 1
}

log_init $@

# source logs.sh

declare -ra param_non_interactive=("non_interactive" "" "" "Run in non-interactive mode")

declare -r utils_original_dir=`pwd`
declare -r utils_script_dir=`cd "$( dirname "$0" )" && pwd`
declare -r utils_script_name=`basename "$0"`
declare utils_script_params="$@ $TAKIPI_ADDITIONAL_SCRIPT_PARAMS"
declare utils_non_interactive_mode="0"

function utils_usage()
{
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_non_interactive[0]}" "${param_non_interactive[3]}" "${param_non_interactive[2]}"
}

function utils_parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi

		case $1 in
			--${param_non_interactive[0]}|-${param_non_interactive[0]}|-${param_non_interactive[1]}|--${param_non_interactive[1]})
				utils_non_interactive_mode="1"
				log $verbose "Param: Non interactive mode"
				shift 1
			;;
			*)
				shift 1
			;;
		esac
	done
}

function utils_init()
{
	utils_parse_command_line $@
	
	log $verbose "Changing working directory to: $utils_script_dir"
	
	cd $utils_script_dir
}

function utils_command_exists()
{
	local program=$1

	which which >/dev/null 2>&1

	if [ $? -eq "0" ]; then
		which $program
	else
		for cur_path in ${PATH//:/ }; do
			if [ -x "$cur_path/$program" ]; then
				return 0
			fi
		done

		return 1
	fi
}

function utils_array_keep_duplicate()
{
	local first_array=$1
	local second_array=$2
	local result=()
	
	for first_item in ${first_array[@]}; do 
		for second_item in ${second_array[@]}; do 
			if [ "$first_item" == "$second_item" ]; then
				result=(${result[@]} $first_item)
			fi
		done
	done
	
	echo ${result[*]}
}

function utils_create_directories()
{
	local directories=$@
	
	for directory in $directories; do
		mkdir -p $directory
	done
}

function utils_is_writable()
{
	local file_or_dir=$1
	
	if [ ! -e "$file_or_dir" ]; then
		echo "$file_or_dir not found"
		return 1
	fi
  
	if [ ! -w $file_or_dir ]; then 
		return 1
	fi
	
	return 0
}

function utils_extract_domain_from_url()
{
	local original_url=$1
	
	local protocol_matcher=".*:\/\/"
	local port_matcher="\(.*\):.*"
	local path_matcher="\([^/]\)\/.*"
	
	echo $original_url | 
		sed "s/$protocol_matcher//" | 
		sed "s/$port_matcher/\1/" | 
		sed "s/$path_matcher/\1/"
}

function utils_extract_protocol_from_url()
{
	local original_url=$1
	local default_value=$2
	
	local protocol_matcher="\(.*\):\/\/.*"
	
	echo $original_url | grep $protocol_matcher >/dev/null 2>/dev/null
	
	if [ $? -eq "0" ]; then
		echo $original_url | sed "s/$protocol_matcher/\1/"
	else
		echo $default_value
	fi
}

function utils_extract_port_from_url()
{
	local original_url=$1
	local default_value=$2
	
	local protocol_matcher=".*:\/\/"
	local domain_matcher=".*:\(.*\)"
	local path_matcher="\([^/]\)\/.*"
	
	echo $original_url | grep ":[0-9]" >/dev/null 2>/dev/null
	
	if [ $? -eq "0" ]; then
		echo $original_url | 
			sed "s/$protocol_matcher//" | 
			sed "s/$domain_matcher/\1/" | 
			sed "s/$path_matcher/\1/"
	else
		echo $default_value
	fi
}

function utils_total_ram_in_megabyte()
{
	local total_ram_in_bytes=`cat /proc/meminfo | grep MemTotal: | awk '{ print $2 }'`
	echo $(($total_ram_in_bytes / 1024))
}

function utils_calc_memory_percent_in_megabyte()
{
	local percent=$1
	local min_value=$2
	local total_megabyte=$3

	if [ -z "$total_megabyte" ]; then
		total_megabyte=`utils_total_ram_in_megabyte`
	fi

	local result=$(($total_megabyte * $percent / 100))
	
	if [ "$result" -gt "1024" ]; then
		result=$(($result / 1024 * 1024))
	fi

	if [ -n "$min_value" ]; then
		if [ "$result" -lt "$min_value" ]; then
			result="$min_value"
		fi
	fi
	
	echo "$result"
}

function utils_add_valiable_to_env_file()
{
	local env_file=$1
	local variable_name=$2
	local variable_value=$3
	
	if [ -n "$variable_value" ]; then
		
		if [ -r $env_file ]; then
			sed -i s/export\ $variable_name=.*//g $env_file
		fi
		
		log $verbose "Updating $env_file: $variable_name = $variable_value"
		echo "export $variable_name=$variable_value" >> $env_file
	fi
}

function utils_add_valiable_to_properties_file()
{
	local properties_file=$1
	local variable_name=$2
	local variable_value=$3
	
	if [ -n "$variable_value" ]; then
		
		if [ -r $properties_file ]; then
			sed -i s/$variable_name=.*//g $properties_file
		fi
		
		log $verbose "Updating $properties_file: $variable_name = $variable_value"
		echo "$variable_name=$variable_value" >> $properties_file
	fi
}

function utils_remove_empty_lines_from_file()
{
	local file_name=$1
	
	sed -i '/^$/d' $1
}

function utils_wait_for_process()
{
	local timeout=$1
	local pid_waiting_for=$2

	local kill_mode
	let "kill_mode=15"

	# Most often, process will die in 0.5 second
	printf "Stopping process $pid_waiting_for..."
	sleep 0.5

	if [ "$timeout" == "0" ]; then
		kill_mode=9
	fi

	while  kill -0 $pid_waiting_for >& /dev/null; do
		if [ $kill_mode -eq 9 ]; then
			log $info "Forcing process termination: $pid_waiting_for"
			kill -9 $pid_waiting_for >& /dev/null

			return 0
		fi

		sleep 1
		let "timeout=$timeout-1"

		printf "."

		if [ $timeout -le 0 ]; then
			let "kill_mode=9"
		fi
	done

	printf "\n"
	
	return 0
}

function utils_array_contains()
{
	local value=$1

	for cur in "${@:2}"; do
		if [ "$cur" == "$value" ] ; then
			return 0
		fi
	done
	
	return 1
}

function utils_safe_move_dir()
{
	local src_dir=$1
	local dst_dir=$2
	local clean_dst=$3
	
	if [ ! -d "$src_dir" ]; then
		return 0
	fi
	
	local move_in_progress_file="$dst_dir/moved"
	
	if [ ! -r $move_in_progress_file ]; then
		if [ "$clean_dst" == "true" ]; then
			log $verbose "Removing dest directory $dst_dir"
			rm -rf $dst_dir
		fi
	fi
	
	mkdir -p $dst_dir
	touch $move_in_progress_file
	
	mv -f $src_dir/* $dst_dir/
	
	if [ "$?" != "0" ]; then
		log $error "Error moving $src_dir to $dst_dir"
		return 1
	fi
	
	rm -r $src_dir
	rm $move_in_progress_file
	
	return 0
}

function utils_safe_move_file()
{
	local src_file=$1
	local dst_file=$2
	
	if [ ! -f "$src_file" ]; then
		return 0
	fi
	
	log $verbose "Start moving $src_file to $dst_file"
	
	local dst_parent_dir=$( dirname $dst_file )
	
	mkdir -p $dst_parent_dir
	
	mv $src_file $dst_file
	
	if [ "$?" != "0" ]; then
		log $error "Error moving $src_file to $dst_file"
		return 1
	fi
	
	log $info "successfully move $src_file to $dst_file"
	
	return 0
}

function utils_to_absolute_path()
{
	local path=$1
	local cwd=$2

	if [[ $path != /* ]]; then
		path=$cwd/$path
	fi

	echo $path
}

function utils_preserve_old_version()
{
	local origfile=$1
	local newfile=$2

	if [ -r "$origfile" -a -r "$newfile" ]; then
		log $verbose "  Removing $newfile"
		rm "$newfile"
	fi
}

function utils_list_available_functions()
{
	typeset -f | awk '/ \(\) $/ && !/^main / {print $1}'
}

function utils_concat_paths() 
{
	local path_begin=$1
	local path_end=$2

	if [[ ! "$path_begin" == */ ]]; then
		path_begin="$path_begin/"
	fi

	echo "${path_begin}${path_end}"
}

function utils_replace_underscore_with_dots()
{
	local source_file=$1
	local file_content=$(cat "$source_file")
	local result_content=$(echo "$file_content" | sed ":b; s/^\([^=]*\)*\./\1_/; tb;")

	echo  "$result_content"
}

function utils_replace_content()
{
	local source_file=$1
	local old_content=$2
	local new_content=$3
	
	if [ ! -r $source_file ]; then
		log $error "Can't replace, file not found $source_file"
		return 1
	fi
	
	log $verbose "Replacing '$old_content' with '$new_content' in '$source_file'"
	
	if ! sed -i "s|$old_content|$new_content|g" $source_file; then
		log $error "failed to replace '$old_content' with '$new_content' in '$source_file'"
		return 1
	fi
	
	return 0;
}

function utils_append_if_missing()
{
	local string_to_append=$1
	local str=$2
	
	if [[ $str == $string_to_append* ]]; then
		echo $str
		return
	fi
	
	echo "$string_to_append$str"
}

function utils_replace_substring()
{
	local orig_string=$1
	local replace_string=$2
	local set_string=$3
	
	echo "${orig_string//$replace_string/$set_string}"
}

function utils_delete_directory()
{
	local dir_to_delete=$1
	local empty_dir=$2
	
	if [ ! -d "$dir_to_delete" ]; then
		log $warn "directory not exists $dir_to_delete"
		return 1
	fi
	
	if [ "$dir_to_delete" == "/" -o "$dir_to_delete" == "" ]; then
		log $warn "Cannot Delete $dir_to_delete directory"
		return 1
	fi
	
	local has_failure="false"
	
	local delete_command="rm -r "
	
	utils_command_exists "rsync" >/dev/null 2>&1
	
	if [ $? -eq "0" ]; then
		local rsync_progress_param=""
		
		if [ "$log_level" == "$verbose" ]; then
			rsync_progress_param="--progress"
		fi
		
		delete_command="rsync -a $rsync_progress_param --delete $empty_dir/ "
		
		
		if ! mkdir -p $empty_dir; then
			return 1
		fi
	fi
	
	log $verbose "Start deleting $dir_to_delete"
	
	for entry in `ls $dir_to_delete`; do
		local entry_path="$dir_to_delete/$entry"
		log $verbose "	Deleting $entry_path"
		
		if [ -d $entry_path ]; then
			if ! $delete_command "$entry_path"; then
					log $warn "Failed to delete $entry_path"
					has_failure="true"
			fi
		fi
		
		if [ -f $entry_path ]; then
			if ! rm "$entry_path"; then
				log $warn "Failed to delete $entry_path"
				has_failure="true"
			fi
		fi
	done
	
	rm -rf $empty_dir
	
	if [ "$has_failure" == "true" ]; then
		return 1
	fi
	
	log $info "$dir_to_delete successfully deleted!"
	
	return 0
}

utils_init $utils_script_params

# An equivalent list exists in InstallerReportServlet.java
#

























# source network.sh
# source reports-codes.sh

declare report_base_url=""
declare report_indentifier=""

function report_init()
{
	report_base_url=$1
	report_indentifier=$2
}

function report_status()
{
	if [ -z "$report_base_url" ]; then
		return 1
	fi
	
	if [ "$OVEROPS_DISABLE_INSTALLER_REPORTS" == "true" ]; then
		return 0
	fi
	
	local report_code=$1
	local extra_data=$2
	local encoded_extra_data=`network_encode_url $extra_data`
	local url=""
	
	if [ $report_code -ne 8 ]; then
		url="${report_base_url}service/ir?sid=$report_indentifier&status=$report_code&os=nix&es=$encoded_extra_data"
	else
		url="${report_base_url}service/ir?status=$report_code&os=nix&kp=$report_indentifier&es=$encoded_extra_data"
	fi
	
	network_download $url /dev/null "1" "5"
	
	return 0
}

# source logs.sh
# source reports.sh

declare -ra param_advanced_init=("advanced_init" "" "" "Advanced init system detector")
declare -ra param_legacy_init=("legacy_init" "" "" "Advanced init system detector")

declare os_smart_init_type_detection="1"
declare os_distribution_name=""
declare os_default_configuration_dir=""
declare os_machine_architecture=""
declare os_machine_name=""
declare os_is_sudo="0"
declare os_init_system_type=""
declare os_root_user_name="root"
declare os_root_group_name="root"
declare os_sigterm_number=15
declare os_sigkill_number=9
declare os_modern_init_type_detection="1"

function os_usage()
{
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_advanced_init[0]}" "${param_advanced_init[3]}" "${param_advanced_init[2]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_legacy_init[0]}" "${param_legacy_init[3]}" "${param_legacy_init[2]}"
}

function os_parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi

		case $1 in
			--${param_advanced_init[0]}|-${param_advanced_init[0]}|-${param_advanced_init[1]}|--${param_advanced_init[1]})
				os_smart_init_type_detection="1"
				log $verbose "Param: Smart init"
				shift 1
			;;
			--${param_legacy_init[0]}|-${param_legacy_init[0]}|-${param_legacy_init[1]}|--${param_legacy_init[1]})
				os_smart_init_type_detection="0"
				log $verbose "Param: Legacy init"
				shift 1
			;;
			*)
				shift 1
			;;
		esac
	done
}

function os_init()
{
	if [ `id -u` -eq 0 ]; then
		os_is_sudo="1"
	fi

	os_parse_command_line $@
	os_detect_distro

	# The modern method is the prefered one since it doesn't guess it but
	#	actually checks what runs. However we can't start using it before
	#	testing and that's why we have this flag. 
	#
	# The Hybrid installer turn on this flag and if we'll see that everything
	#	goes well we'll use it for Collector installer too
	#
	if [ "$os_modern_init_type_detection" == "1" ]; then
		os_detect_init_type_modern
	else
		os_detect_init_type
	fi

	os_init_default_configuration_dir
	os_machine_architecture=`uname -m`
	os_machine_name=`hostname`
	os_system_information=`uname -a`
}

function os_detect_distro()
{
	log $verbose "Detecting OS distro..."
	
	if [ ! "$os_distribution_name" ]; then
		if [ -f /etc/lsb-release ]; then
			local distrib_line=$(cat /etc/lsb-release | grep '^DISTRIB_ID=')
			
			if [ ! -z "$distrib_line" ]; then
				os_distribution_name=${distrib_line:11}
			fi
		fi
	fi
	
	if [ ! "$os_distribution_name" ]; then
		if [ -f /etc/os-release ]; then
			local id_like_line=$(cat /etc/os-release | grep '^ID_LIKE=')
			
			if [ ! -z "$id_like_line" ]; then
				local id_like=${id_like_line:8}
				
				if [ "$id_like" = "suse" -o "$id_like" = "\"suse\"" ]; then
					os_distribution_name="SuSE"
				fi
			fi
		fi
	fi
	
	if [ "$os_distribution_name" ]; then
		log $verbose "$os_distribution_name detected."
	elif [ -f /etc/debian_version ]; then
		os_distribution_name="Ubuntu"
		log $verbose "Ubuntu/Debian detected."
	elif [ -f /etc/redhat-release ]; then
		os_distribution_name="Redhat"
		log $verbose "RedHat/Fedora detected."
	elif [ -f /etc/centos-release ]; then
		os_distribution_name="Redhat"
		log $verbose "CentOS detected."
	elif [ -f /etc/gentoo-release ]; then
		os_distribution_name="Gentoo"
		log $verbose "Gentoo detected."
	elif [ -f /etc/alpine-release ]; then
		os_distribution_name="Alpine"
		log $verbose "Alpine detected."
	elif [ -f /etc/SuSE-release ]; then
		os_distribution_name="SuSE"
		log $verbose "SuSE detected."
	elif [ -f /etc/arch-release ]; then
		os_distribution_name="Arch"
		log $verbose "Arch Linux detected."
	elif [ -f /etc/system-release ]; then
		os_distribution_name="Redhat"
		log $verbose "Amazon Linux assumed."
	elif [ -d /etc/sysconfig ]; then
		if [ -f /etc/init.d/functions ]; then
			os_distribution_name="Redhat"
			log $verbose "RedHat/Fedora assumed."
		elif [ -f /etc/rc.status ]; then
			os_distribution_name="SuSE"
			log $verbose "SuSE assumed."
		fi
	elif [ -d /etc/conf.d ]; then
		os_distribution_name="Gentoo"
		log $verbose "Gentoo assumed."
	elif [ -d /Users ] && [ -d /Applications ]; then
		os_distribution_name="OSX"
		log $verbose "OSX detected"
	else
		os_distribution_name="Ubuntu"
		log $verbose "Ubuntu/Debian assumed."
	fi

	if [ "$os_distribution_name" = "Ubuntu" -o "$os_distribution_name" = "Debian" -o "$os_distribution_name" = "Mint" -o "$os_distribution_name" = "LinuxMint" -o "$os_distribution_name" = "MintLinux" -o "$os_distribution_name" = "\"elementary\""  ]; then
		os_distribution_name="Ubuntu"
	fi
}

function os_detect_init_type()
{
	# Rules:
	#  Arch always uses systemd
	#  Aline always uses openrc
	#  All distros except Ubuntu and Redhat use sysvinit
	#  Ubuntu never uses systemd
	#  Ubuntu prefer upstart over sysvinit
	#  Redhat uses systemd, upstart, sysvinit in that order
	#  In legacy mode both Ubuntu and Redhat behave like other distros
	#
	
	local use_smart_detection="0"
	
	if [ "$os_distribution_name" == "Ubuntu" -o "$os_distribution_name" == "Redhat" ]; then
		if [ "$os_smart_init_type_detection" == "1" ]; then
			use_smart_detection="1"
		fi
	fi
	
	if [ "$os_distribution_name" == "Alpine" ]; then
		os_init_system_type="openrc"
	elif [ "$use_smart_detection" == "0" ]; then
		if [ "$os_distribution_name" = "Arch" ]; then
			os_init_system_type="systemd"
		else
			os_init_system_type="sysvinit"
		fi
	else
		local has_systemd="false"
		local has_upstart="false"

		utils_command_exists systemctl >/dev/null 2>&1

		if [ $? -eq "0" ]; then
			has_systemd="true"

			log $verbose "Init daemon available: systemd"
		fi

		utils_command_exists initctl >/dev/null 2>&1

		if [ $? -eq "0" ]; then
			has_upstart="true"

			log $verbose "Init daemon available: upstart"
		fi
		
		if [ "$has_systemd" == "true" ]; then
			os_init_system_type="systemd"
		elif [ "$has_upstart" == "true" ]; then
			os_init_system_type="upstart"
		else
			os_init_system_type="sysvinit"
		fi
		
		if [ "$os_distribution_name" == "Ubuntu" -a "$os_init_system_type" == "systemd" ]; then
			os_init_system_type="sysvinit" # systemd currently falls back to sysvinit in Ubuntu
		fi
	fi

	log $verbose "Chosen init daemon: $os_init_system_type"
}

function os_detect_init_type_modern()
{
	if [[ $(ls -l /proc/1/exe 2> /dev/null) =~ "init" ]]; then
		if [[ $(init --version 2> /dev/null | grep init) =~ "upstart" ]]; then
			os_init_system_type="upstart"
		else
			os_init_system_type="sysvinit"
		fi
	fi

	if [[ $(ls -l /proc/1/exe 2> /dev/null) =~ "systemd" ]]; then
		os_init_system_type="systemd"
	fi
}

function os_init_default_configuration_dir()
{
	if [ "$os_distribution_name" = "Ubuntu" ]; then
		os_default_configuration_dir=/etc/default
	elif [ "$os_distribution_name" = "Gentoo" -o "$os_distribution_name" = "Alpine" ]; then
		os_default_configuration_dir=/etc/conf.d
	elif [ "$os_distribution_name" = "Arch" ]; then
		os_default_configuration_dir=
	else # "Redhat" / "SuSE"
		os_default_configuration_dir=/etc/sysconfig
	fi
}

function os_get_process_pids()
{
	local process_filter=$1
	
	if [ -z "$process_filter" ]; then
		return 1
	fi

	if [ "$os_distribution_name" == "Alpine" ]; then
		ps -o pid,comm | grep $process_filter | grep -v grep | awk '{ print $1 }'
	else
		ps -C $process_filter -o pid | tail -n +2 | tr -d ' '
	fi
	
	return 0
}

function os_has_library_in_process()
{
	local process_pid=$1
	local library_name=$2
	
	cat /proc/$process_pid/maps 2>&1 | grep $library_name >/dev/null 2>&1
	
	local is_library_found=$?
	
	if [ "$is_library_found" == "0" ]; then
		return 0
	else
		return 1
	fi
}

function os_get_free_space_in_bytes_by_path()
{
	local target=$1
	local existing_target="$target"
	
	while true; do
		if [ -z "$existing_target" ]; then
			break
		fi
		
		if [ -d "$existing_target" ]; then
			break
		fi
		
		existing_target=$(dirname $existing_target)
	done
	
	df -P $existing_target | grep -v Filesystem | awk '{print $4}'
}

function os_get_free_space_by_path()
{
	local target=$1
	local minimal_space=$2
	local existing_target="$target"
	local os_free_space_in_bytes=$(os_get_free_space_in_bytes_by_path $target)
	
	if [ $os_free_space_in_bytes -lt $minimal_space ]; then
		return 1
	else
		return 0
	fi
}

function os_create_user()
{
	local username=$1
	local password=$2
	local homefolder=$3
	[ -z $4 ] && local shell=/bin/bash || local shell=$4

	if [ -z "$(getent passwd $username)" ]; then
		useradd -d $homefolder -s $shell $username &> /dev/null || return 1
		echo "${username}:${password}" | chpasswd &> /dev/null || return 1
	fi

	return 0
}

function os_fix_home_folder_ownership()
{
	local owner=$1
	[ -z $2 ] && local path=$(getent passwd $owner | cut -f6 -d:) || local path=$2

	chown -R ${owner}:${group} $path &> /dev/null || return 1

	return 0
}

os_init $utils_script_params

# source logs.sh
# source os.sh
# source network.sh
# source utils.sh

declare -ra param_skip_java_version=("skipjversion" "" "" "Do not verify Java version")
declare -ra param_install_jdk=("install_jdk" "" "" "Install the JDK")

declare java_provided_jdk_base_path=/opt
declare java_skip_version_check="0"
declare java_should_install_jdk="0"
declare java_home_dir=""
declare java_jvm_lib_file=""
declare java_exe_file=""
declare java_version=""
declare java_provided_download_url="https://s3.amazonaws.com/app-takipi-com/deploy/jdk/takipi-jdk.tar.gz"

function java_usage()
{
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_skip_java_version[0]}" "${param_skip_java_version[3]}" "${param_skip_java_version[2]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_install_jdk[0]}" "${param_install_jdk[3]}" "${param_install_jdk[2]}"	
}

function java_parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi

		case $1 in
			--${param_skip_java_version[0]}|-${param_skip_java_version[0]}|-${param_skip_java_version[1]}|--${param_skip_java_version[1]})
				java_skip_version_check="1"
				log $verbose "Param: Skip java version check"
				shift 1
			;;
			--${param_install_jdk[0]}|-${param_install_jdk[0]}|-${param_install_jdk[1]}|--${param_install_jdk[1]})
				java_should_install_jdk="1"
				log $verbose "Param: Install JDK"
				shift 1
			;;
			*)
				shift 1
			;;
		esac
	done
}

function java_init()
{
	java_parse_command_line $@
	
	if ! java_look_for_java "$java_must_be_jdk"; then
		if [ "$utils_non_interactive_mode" == "0" ]; then
			java_manually_entering_java
		fi
	fi
	
	log $verbose "Java: (home: $java_home_dir) (version: $java_version)"
}

function java_found_valid_java()
{
	if [ -n "$java_jvm_lib_file" -a -n "$java_exe_file" ]; then
		return 0
	fi
	
	return 1
}

function java_list_java_pids() 
{
	os_get_process_pids java
}

function java_install_provided_jdk()
{
	local temp_jdk_file=`mktemp /tmp/jdk-jdk-XXXXXX`
	local temp_jdk_file_tarball="${temp_jdk_file}.tar.gz"
	
	if ! network_download "$java_provided_download_url" "$temp_jdk_file_tarball"; then
		return 1
	fi
	
	tar -C $java_provided_jdk_base_path -zxf $temp_jdk_file_tarball >/dev/null 2>&1
	rm -f $temp_jdk_file_tarball >/dev/null 2>&1
	
	java_set_java_if_valid "1" "$java_provided_jdk_base_path/takipi-jdk"
}

function java_set_java_if_valid()
{
	local jdk_only=$1
	local java_dir=$2
	
	if [ -z "$java_dir" ]; then
		return 1
	fi
	
	local available_locations="$java_dir $java_dir/bin/java $java_dir/jre/bin/java $java_dir/java"
	
	local parent1=$(dirname $java_dir)
	local parent2=$(dirname $parent1)
	local parent3=$(dirname $parent2)
	
	local available_locations="$available_locations $parent1/jre/bin/java $parent2/jre/bin/java $parent3/jre/bin/java"
	
	for java_exe in $available_locations; do
		if [ ! -x $java_exe -o -d $java_exe ]; then
			continue
		fi
		
		if [ "$java_skip_version_check" == "0" ]; then
			local java_tool_options_backup=""
			
			if [ -n "$JAVA_TOOL_OPTIONS" ]; then
				java_tool_options_backup="$JAVA_TOOL_OPTIONS"
				unset JAVA_TOOL_OPTIONS
			fi
			
			java_version=$("$java_exe" -version 2>&1 | awk -F '"' '/version/ {print $2}')
			local bit_version_1=$("$java_exe" -version 2>&1 | awk 'END{print $2}')
			local bit_version_2=$("$java_exe" -version 2>&1 | awk 'END{print $3}')
			
			if [ -n "$java_tool_options_backup" ]; then
				export JAVA_TOOL_OPTIONS="$java_tool_options_backup"
			fi
			
			if [[ "$java_version" == "1."* && "$java_version" < "1.8" ]]; then
				continue
			fi
			
			if [ "$bit_version_1" != "64-Bit" -a "$bit_version_2" != "64-Bit" ]; then
				continue
			fi
		fi
		
		local java_exe_length=${#java_exe}-9
		local lib_file_possible_path_1="${java_exe:0:$java_exe_length}/lib/amd64/server/libjvm.so"
		local lib_file_possible_path_2="${java_exe:0:$java_exe_length}/lib/server/libjvm.so"
		
		local lib_file
		
		if [ -r $lib_file_possible_path_1 ]; then
			lib_file=$lib_file_possible_path_1
		elif [ -r $lib_file_possible_path_2 ]; then
			lib_file=$lib_file_possible_path_2
		else
			continue
		fi
		
		# lll: This is a hack, we should change the whole function a little bit.
		#	today it doesn't know for sure what is the java_home, where is the 
		#	jdk root directory etc.. It just try everything until it finds something.
		# Although I do have the time to fix it, I don't have the time to test it,
		#	cause this refactor requires a lot of testing for all distros * and too
		#	many variations. Consider it before you refactor this method.
		#
		local java_exe_length2=${#java_exe}-12
		local home_dir="${java_exe:0:$java_exe_length2}"
		
		if [ ! -d "$home_dir" ]; then
			home_dir="${java_exe:0:$java_exe_length}"	
		fi
		
		if [ "$jdk_only" == "1" ]; then
			if ! java_is_jdk $home_dir; then
				log $verbose "Searching for a JDK - $java_exe is not in a JDK folder"
				continue
			fi
		fi
		
		log $verbose "Java found at $java_exe"
		
		if [ "$java_skip_version_check" == "1" ]; then
			log $verbose "Skipped Java version check."
		fi
		
		java_home_dir=$home_dir
		java_jvm_lib_file=$lib_file
		java_exe_file=$java_exe
		return 0
	done

	return 1
}

function java_is_jdk()
{
	local home_dir=$1
	local tools_file="$home_dir/lib/tools.jar"
	local jre_dir="$home_dir/jre"
	
	if [ -d "$jre_dir" -a -r "$tools_file" ]; then
		return 0
	fi
	
	return 1
}

function java_report_status()
{
	if [ "X`type -t java_report_status_hook`" == "Xfunction" ]; then
		java_report_status_hook $1
	fi
}

function java_look_for_java()
{
	local jdk_only=$1
	
	log $verbose "Looking for Java (jdk only? $jdk_only)"
	
	log $verbose "Search for Java lib according to JAVA_HOME: $JAVA_HOME"
	
	if java_set_java_if_valid "$jdk_only" "$JAVA_HOME"; then
		return 0
	fi
	
	log $verbose "Search for Java lib according to PATH: $PATH"
	
	if type -p java >/dev/null 2>&1; then
		local temp_java_bin=$(readlink -f `type -p java`)

		if java_set_java_if_valid "$jdk_only" "$temp_java_bin"; then
			return 0
		fi
	fi
	
	log $verbose "Search for Java lib according to pid"

	if java_find_according_to_pid "$jdk_only"; then
		return 0
	fi
	
	log $verbose "Brute force to find java"

	if brute_force_java_searching "$jdk_only"; then
		return 0
	fi

	return 1
}

function java_find_according_to_pid()
{
	local jdk_only=$1
	
	java_report_status 53

	local temp_java_bin=""
	local java_pids=`java_list_java_pids`

	for pid in $java_pids; do
		temp_java_bin=$(readlink -f "/proc/$pid/exe")

		if java_set_java_if_valid "$jdk_only" "$temp_java_bin"; then
			java_report_status 54
			return 0
		fi
	done

	java_report_status 55
	return 1
}

function brute_force_java_searching()
{
	local jdk_only=$1
	
	local common_jdk_locations="/usr/java/default /usr/lib/jvm/java /usr/java/default-java /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-1.5.0-sun /usr/lib/j2sdk1.5-sun /usr/lib/j2sdk1.5-ibm /usr/lib/jvm/jre /usr/lib/jvm/default-java /usr/java /usr/java/latest /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-7-openjdk /usr/lib/jvm/java-7-openjdk-amd64 /usr/lib/jvm/java-7-sun /usr/lib/jvm/java-openjdk /usr/lib/jvm/java-7-oracle /usr/lib/jvm/oracle-jre-bin-1.7 /usr/lib/jvm/oracle-jre-bin-1.6"

	for java_home in $common_jdk_locations; do
		local temp_java_bin=$(readlink -f "$java_home/bin/java")

		if java_set_java_if_valid "$jdk_only" "$temp_java_bin"; then
			return 0
		fi

		temp_java_bin=$(readlink -f "$java_home/jre/bin/java")

		if java_set_java_if_valid "$jdk_only" "$temp_java_bin"; then
			return 0
		fi
		
		temp_java_bin=$(readlink -f "$java_home")
		
		if java_set_java_if_valid "$jdk_only" "$temp_java_bin"; then
			return 0
		fi
	done

	return 1
}

function java_manually_entering_java()
{
	log $verbose "Manually entering java"
	
	java_report_status 50

	local user_temp_java_bin=""
	log $info "The installation was not able to automatically locate a valid 64-bit Java installation."
	read -e -p "> Please enter a Java executable path (e.g. /usr/bin/java): " user_temp_java_bin < /dev/tty

	local temp_java_bin=$(readlink -f "$user_temp_java_bin")

	if java_set_java_if_valid "0" "$temp_java_bin"; then
		java_report_status 51
		return 0
	fi
	
	java_report_status 52
	return 1
}

function java_run()
{
	if ! java_found_valid_java; then
		return 1
	fi
	
	local java_tool_options_backup=""
	
	if [ -n "$JAVA_TOOL_OPTIONS" ]; then
		java_tool_options_backup="$JAVA_TOOL_OPTIONS"
		unset JAVA_TOOL_OPTIONS
	fi
	
	log $verbose "Running: $java_exe_file $*"
	
	$java_exe_file $@
	
	local java_return_value=$?
	
	if [ -n "$java_tool_options_backup" ]; then
		export JAVA_TOOL_OPTIONS="$java_tool_options_backup"
	fi
	
	return $java_return_value
}

function java_check_connection()
{
	local url=$1
	local bootstrap_jar=$2
	local params="-url $url"
	
	if [ log_is_verbose ]; then
		params="$params -verbose true"
	fi
	
	local jvm_params=""
	jvm_params="$jvm_params -Dhttps.proxyHost=$network_proxy_host"
	jvm_params="$jvm_params -Dhttps.proxyPort=$network_proxy_port"
	jvm_params="$jvm_params -Dhttps.proxyUser=$network_proxy_user"
	jvm_params="$jvm_params -Dhttps.proxyPassword=$network_proxy_pass"
	
	java_run $jvm_params -cp $bootstrap_jar m.M checkconnection $params
}

function java_list_unattached_jvms()
{
	local overops_lib_name=$1
	local overops_exe_name=$2
	
	local running_pids=($(ps -e -o pid | tail -n +2))
	local found_java_process=()
	
	for pid in "${running_pids[@]}"; do
		if ! os_has_library_in_process "$pid" "libjvm.so"; then
			continue
		fi
		
		if os_has_library_in_process "$pid" "$overops_lib_name"; then
			continue
		fi
		
		local is_overops_daemon=`ps -e | grep $pid | grep "$overops_exe_name" >/dev/null 2>&1`
		
		if [ -n "$is_overops_daemon" ]; then
			continue
		fi
		
		found_java_process=(${found_java_process[@]} $pid)
	done
	
	echo ${found_java_process[*]}
}

function java_pretty_print_java_processes()
{
	local java_pids=$1
	
	if [ ${#java_pids[@]} == 0 ]; then
		return
	fi
	
	local clear_style='\E[00m'
	local style='\E[1m\E[4m'

	printf "    ${style}PID${clear_style}%-7s${style}Application${clear_style}\n" ""

	local java_pids_comma_seperated=$(echo "${java_pids[*]}" | sed 's/ /,/g')
	local java_processes_info=$(ps -p $java_pids_comma_seperated -o pid,args |  tail -n +2 )
	
	echo "$java_processes_info" | awk \
		' {
			if ($2 !~ /java.?$/)
			{
				# non standard java process.
				printf "    %-10s%s \n", $1, $2;	
				next;
			}
			
			skipNext = "false";
			marked = "false"

			for (i = 3; i <= NF; i++)
			{
				if (skipNext == "true")
				{
					skipNext = "false";
					continue;
				}

				if ($i == "-jar")
				{
					nextIdx = i + 1;
					printf "    %-10s%s \n", $1, $nextIdx;
					marked = "true";
					break;
				}

				if ($i !~ /^-/)
				{
					printf "    %-10s%s \n", $1, $i;
					marked = "true";
					break;
				}

				if ($i == "-cp" || $i == "-classpath")
				{
					skipNext = "true";
				}
			}

			if (marked == "false")
			{
				printf "    %-10s%s \n", $1, $2;
			}
		} '
}

function java_show_invalid_java_message()
{
	local product_name=$1
	
	echo "Java not valid!"
	echo "Please point the JAVA_HOME environment variable to a valid 64-bit Java installation,"
	echo "e.g. 'export JAVA_HOME=/usr/lib/jvm/java-6-openjdk/jre',"
	echo "or make sure the symbolic link at /usr/bin/java is valid."
	echo " "
	echo "$product_name installation aborted!"
}

function java_heap_size_to_param()
{
	local heap_size=$1
	local current_java_opts=$2
	
	if [ -z "$heap_size" ]; then
		return
	fi
	
	local has_max_heap=`echo $current_java_opts | grep Xmx`
	local has_min_heap=`echo $current_java_opts | grep Xms`
	
	if [ -n "$has_max_heap" -o -n "$has_min_heap" ];then
		return
	fi
	
	echo "-Xms${heap_size}m -Xmx${heap_size}m"
}

java_init $utils_script_params

# source logs.sh
# source os.sh

declare -ra param_https_proxy=("https_proxy" "" "" "An Https proxy used to connect to the Internet")
declare -ra param_no_check_certificate=("no_check_certificate" "" "" "Skip certificate validation")
declare -ra param_verbose_network=("verbose_network" "" "" "")

declare network_https_proxy=""
declare network_no_check_certificate="0"
declare network_proxy_host=""
declare network_proxy_port=""
declare network_proxy_user=""
declare network_proxy_pass=""
declare network_has_wget="0"
declare network_has_curl="0"
declare verbose_network="0"

function network_usage()
{
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_https_proxy[0]}" "${param_https_proxy[3]}" "${param_https_proxy[2]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_no_check_certificate[0]}" "${param_no_check_certificate[3]}" "${param_no_check_certificate[2]}"
}

function network_parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi

	 	case $1 in
	 		--${param_https_proxy[0]}|-${param_https_proxy[0]}|--${param_https_proxy[1]}|-${param_https_proxy[1]})
				shift 1
				network_https_proxy=$1
				log $verbose "Param: ${param_https_proxy[0]} = $network_https_proxy"
				shift 1
			;;
			--${param_https_proxy[0]}=*|-${param_https_proxy[0]}=*|--${param_https_proxy[1]}=*|-${param_https_proxy[1]}=*)
				network_https_proxy=${1#*=}
				log $verbose "Param: ${param_https_proxy[0]} = $network_https_proxy"
				shift 1
			;;
			--${param_no_check_certificate[0]}|-${param_no_check_certificate[0]}|-${param_no_check_certificate[1]}|--${param_no_check_certificate[1]})
				network_no_check_certificate="1"
				log $verbose "Param: Skip certificate validation"
				shift 1
			;;
			--${param_verbose_network[0]}|-${param_verbose_network[0]}|-${param_verbose_network[1]}|--${param_verbose_network[1]})
				verbose_network="1"
				log $verbose "Param: Verbose network"
				shift 1
			;;
			*)
				shift 1
			;;
		esac
	done
}

function network_init() 
{
	network_parse_command_line $@
	
	utils_command_exists wget >/dev/null 2>&1
	
	if [ $? -eq "0" ]; then
		network_has_wget="1"
	fi
	
	utils_command_exists curl >/dev/null 2>&1

	if [ $? -eq "0" ]; then
		network_has_curl="1"
	fi
	
	log $verbose "Network initialized, wget? $network_has_wget, curl? $network_has_curl"
}

function network_set_proxy()
{
	local new_network_https_proxy=$1
	
	if [ -z "$new_network_https_proxy" ]; then
		return 0
	fi
	
	network_https_proxy=$new_network_https_proxy
	local proxySuffix=${network_https_proxy##*/}

	local old_ifs=$IFS
	IFS='@' read -ra proxy <<< "$proxySuffix"

	if [ ${#proxy[@]} == 2 ]; then

		IFS=':' read -ra userAndPass <<< "${proxy[0]}"

		if [ ${#userAndPass[@]} == 2 ]; then
			network_proxy_user=${userAndPass[0]}
			network_proxy_pass=${userAndPass[1]}
		fi

		IFS=':' read -ra hostAndPort <<< "${proxy[1]}"

		if [ ${#hostAndPort[@]} == 2 ]; then
			network_proxy_host=${hostAndPort[0]}
			network_proxy_port=${hostAndPort[1]}
		fi
	fi

	if [ ${#proxy[@]} == 1 ]; then

		IFS=':' read -ra hostAndPort <<< "${proxy[0]}"

		if [ ${#hostAndPort[@]} == 2 ]; then
			network_proxy_host=${hostAndPort[0]}
			network_proxy_port=${hostAndPort[1]}
		fi

	fi
	
	IFS=$old_ifs
}

function network_can_download()
{
	if [ "$network_has_wget" != "1" -a "$network_has_curl" != "1" ]; then
		return 1
	else
		return 0
	fi
}

function network_file_is_reachable()
{
	local ret
	local url=$1
	local response

	if [ "$network_has_curl" == "1" ]; then
	    response=$(curl -I --silent --write-out %{http_code} --output /dev/null $url &> /dev/null ;ret=$?)
	elif [ "$network_has_wget" == "1" ]; then
	    response=$(wget --spider -S $url 2>&1 |grep 'HTTP/' | awk '{print $2}')
	fi

	if [[ $(echo $response | grep -q "403\|404\|500") ]]; then
		return 1
	fi
	
	return $ret
}

function network_is_port_used()
{
	local port_to_check=$1
	local taken_valid_pid=$2
	
	if ! which netstat >/dev/null 2>&1; then
		return 127
	fi
	
	if [ -n "$taken_valid_pid" ]; then
		if [[ `netstat -nlutp | grep -w $port_to_check | grep -v $taken_valid_pid` ]] >/dev/null 2>&1; then
			return 0
		fi
	else
		if [[ `netstat -nlutp | grep -w $port_to_check` ]] >/dev/null 2>&1; then
			return 0
		fi
	fi
	
	return 1
}

function network_download()
{
	local from_url=$1
	local to_file=$2
	local log_silent=$3
	local connect_timeout=$4
	local retries=$5
	
	if [ -z "$retries" ]; then
		retries=5
	fi
	
	local params=""
	local download_command=""
	
	if [ "$network_has_wget" == "1" ]; then
		if [ "$network_https_proxy" != "" ]; then
			params="-e https_proxy=$network_https_proxy"
		fi

		if [ "$network_no_check_certificate" == "1" ]; then
			params="$params --no-check-certificate"
		fi
		
		if [ -n "$connect_timeout" ]; then
			params="-T $connect_timeout --connect-timeout=$connect_timeout $params"
		fi
		
		if [ "$os_distribution_name" == "Alpine" ]; then
			download_command="wget -t $retries -O $to_file $from_url" 
		else
			download_command="wget -t $retries $params -O $to_file $from_url"
		fi
	else
		if [ "$network_https_proxy" != "" ]; then
			params="-x $network_https_proxy"
		fi

		if [ -n "$connect_timeout" ]; then
			params="--max-time $connect_timeout --connect-timeout $connect_timeout $params"
		fi

		if [ "$os_distribution_name" == "Alpine" ]; then
			download_command="curl -o $to_file -L $from_url"
		else
			download_command="curl $params -o $to_file -L $from_url"
		fi
	fi
	
	if [ "$verbose_network" == "1" ]; then
		log $verbose "$download_command"
	fi
	
	if [ "$log_silent" == "1" ]; then
		$download_command >/dev/null 2>&1
	else
		$download_command
	fi
}

function network_encode_url()
{
	local url="$1"
	
	local urlLen=${#url}
	local encoded=""

	for (( i=0 ; i < urlLen ; i++ )); do
		local curChar=${url:$i:1}
		case "$curChar" in
			[-_.~a-zA-Z0-9])
				o="${curChar}"
				;;
			*)
				o=$(printf '%%%02x' "'$curChar")
				;;
		esac
		encoded="${encoded}${o}"
	done

	echo "$encoded"
}

network_init $utils_script_params

# source logs.sh

declare lib32_dir=""
declare lib64_dir=""

function dynamic_libs_init()
{
	if [ -d "/usr/lib" -a -d "/usr/lib64" ]; then
		lib32_dir="/usr/lib"
		lib64_dir="/usr/lib64"
	elif [ -d "/usr/lib" ]; then
		lib32_dir="/usr/lib32"
		lib64_dir="/usr/lib"
	elif [ -d "/lib" -a -d "/lib64" ]; then
		lib32_dir="/lib"
		lib64_dir="/lib64"
	elif [ -d "/lib" ]; then
		lib32_dir="/lib32"
		lib64_dir="/lib"
	else
		log $error "Unable to find appropriate lib directory."
		return 1
	fi
	
	if [ ! -d "$lib32_dir" ]; then
		mkdir "$lib32_dir"
	fi
	
	return 0
}

function dynamic_libs_add_location()
{
	local library_name=$1
	local location_dir=$2
	
	log $verbose "Registering $library_name with the dynamic linker..."

	if [ -d "/etc/ld.so.conf.d" ]; then
		echo "$location_dir" > /etc/ld.so.conf.d/$library_name.conf
	else # Alpine
		echo "$location_dir" >> /etc/ld.so.conf
	fi

	ldconfig >/dev/null 2>&1
	/sbin/ldconfig >/dev/null 2>&1
}

function dynamic_libs_install_globally()
{
	local library_file_64=$1
	local library_file_32=$2
	
	log $verbose "Installing library $library_file_64"
	
	local library_name_64=`basename $library_file_64`
	ln -sf $library_file_64 $lib64_dir/$library_name_64 >/dev/null 2>&1
	
	if [ -n "$library_file_32" ]; then
		local library_name_32=`basename $library_file_32`
		ln -sf $library_file_32 $lib32_dir/$library_name_32 >/dev/null 2>&1
	fi

	ldconfig >/dev/null 2>&1
	/sbin/ldconfig >/dev/null 2>&1
}

function dynamic_libs_replace_globally()
{
	local library_base_name=$1
	local library_file_64=$2
	local library_file_32=$3
	
	log $verbose "Replacing library $library_base_name"
	
	if [ -h "$lib64_dir/$library_base_name" ]; then
		rm -f "$lib64_dir/$library_base_name" >/dev/null 2>&1
		cp "$library_file_64" "$lib64_dir/$library_base_name"
	fi
	
	if [ -h "$lib32_dir/$library_base_name" ]; then
		rm -f "$lib32_dir/$library_base_name" >/dev/null 2>&1
		cp "$library_file_32" "$lib32_dir/$library_base_name"
	fi
}

dynamic_libs_init $utils_script_params

# source logs.sh
# source os.sh
# source reports.sh

function daemon_stop()
{
	local daemon_name=$1
	local daemon_exe_name=$2
	local skip_kill=$3

	log $verbose "Stopping $daemon_name daemon ($os_distribution_name, $os_init_system_type)..."
	
	systemctl stop $daemon_name.service >/dev/null 2>&1
	/etc/init.d/$daemon_name stop >/dev/null 2>&1
	initctl stop $daemon_name >/dev/null 2>&1
	rc-service $daemon_name stop >/dev/null 2>&1
	
	local daemon_pid=`os_get_process_pids $daemon_exe_name`

	if [ "$skip_kill" != "true" ]; then
        if [ -n "$daemon_pid" ]; then
            kill -9 $daemon_pid
        fi
	fi
	
	return 0
}

function daemon_start_upstart()
{
	local daemon_name=$1
	local upstart_output=`initctl start $daemon_name 2>&1`
	
	if [ $? -eq "0" ]; then
		return 0
	fi
	
	echo $upstart_output | grep "Job is already running" >/dev/null 2>&1
	
	if [ $? -eq "0" ]; then
		return 0
	fi
	
	return 1
}

function daemon_start()
{
	local daemon_name=$1
	
	log $verbose "Starting $daemon_name ($os_distribution_name, $os_init_system_type)..."
	
	if [ "$os_init_system_type" == "upstart" ]; then
		daemon_start_upstart "$daemon_name"
	elif [ "$os_init_system_type" == "systemd" ]; then
		systemctl start $daemon_name.service >/dev/null 2>&1
	elif [ "$os_init_system_type" == "openrc" ]; then
		rc-service $daemon_name start >/dev/null 2>&1
	else 
		/etc/init.d/$daemon_name start >/dev/null 2>&1
	fi
	
	return $?
}

function daemon_restart()
{
	local daemon_name=$1
	local daemon_exe_name=$1
	
	daemon_stop $daemon_name $daemon_exe_name
	
	if ! daemon_start "$daemon_name"; then
		return 1
	fi
	
	return 0
}

function daemon_install()
{
	local daemon_name=$1
	local daemon_init_file=$2
	
	log $verbose "Installing $daemon_name ($daemon_init_file) (it: $os_init_system_type)"
	
	chmod +x $daemon_init_file
	
	if [ "$os_init_system_type" == "upstart" ]; then
		local init_file_name="/etc/init/$daemon_name.conf"
		
		cp -f $daemon_init_file "$init_file_name"
		chmod 644 "$init_file_name"
		initctl check-config $daemon_name
	elif [ "$os_init_system_type" == "systemd" ]; then
		local init_file_name="/lib/systemd/system/$daemon_name.service"
		
		cp -f $daemon_init_file "$init_file_name"
		systemctl daemon-reload >/dev/null 2>&1
		systemctl enable $daemon_name.service >/dev/null 2>&1
	else # sysvinit/openrc
		local init_file_name="/etc/init.d/$daemon_name"
		
		if [ "$os_distribution_name" == "Ubuntu" ]; then
			cp -f $daemon_init_file "$init_file_name"
			/usr/sbin/update-rc.d -f $daemon_name remove >/dev/null 2>&1
			/usr/sbin/update-rc.d $daemon_name defaults >/dev/null 2>&1
		elif [ "$os_distribution_name" == "Redhat" ]; then
			cp -f $daemon_init_file "$init_file_name"
			/sbin/chkconfig $daemon_name on >/dev/null 2>&1
		elif [ "$os_distribution_name" == "Gentoo" -o "$os_distribution_name" == "Alpine" ]; then
			cp -f $daemon_init_file "$init_file_name"
			/sbin/rc-update del $daemon_name default >/dev/null 2>&1
			/sbin/rc-update add $daemon_name default >/dev/null 2>&1
		elif [ "$os_distribution_name" = "SuSE" ]; then
			cp -f $daemon_init_file "$init_file_name"
			/sbin/insserv -r $daemon_name >/dev/null 2>&1
			/sbin/insserv -d $daemon_name >/dev/null 2>&1
		else
			log "Error configure sysvinit for $os_distribution_name"
			return 1
		fi
		
		chmod +x "$init_file_name"
	fi
	
	return 0
}

function daemon_uninstall()
{
	local daemon_name=$1
	local default_file=$2
	
	rm -rf /etc/$daemon_name >/dev/null 2>&1
	rm -rf /etc/init.d/$daemon_name >/dev/null 2>&1
	rm -rf /lib/systemd/system/$daemon_name.service >/dev/null 2>&1
	rm -rf /etc/ld.so.conf.d/$daemon_name.conf >/dev/null 2>&1
	rm -rf /etc/init/$daemon_name.conf >/dev/null 2>&1
	
	# Chen - default file is used for provisioning and should be manually configured/removed
	# rm -rf $default_file >/dev/null 2>&1

	# sysvinit / Ubuntu
	/usr/sbin/update-rc.d -f $daemon_name remove >/dev/null 2>&1

	# sysvinit / Gentoo / Alpine
	/sbin/rc-update del $daemon_name default >/dev/null 2>&1

	# sysvinit / RedHat
	/sbin/chkconfig $daemon_name off >/dev/null 2>&1

	# sysvinit/ SuSE
	/sbin/insserv -r $daemon_name >/dev/null 2>&1

	# systemd
	systemctl disable $daemon_name >/dev/null 2>&1
	systemctl daemon-reload >/dev/null 2>&1
}

# source logs.sh
# source utils.sh
# source os.sh
# source dynamic-libs.sh

declare -ra param_auto_agent=("auto_agent" "" "" "")
declare -ra param_smart_attach=("config_attach" "" "" "")

declare agent_auto_agent_enabled="0"
declare agent_smart_attach_enabled="0"

function agent_usage()
{
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_auto_agent[0]}" "${param_auto_agent[3]}" "${param_auto_agent[2]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_smart_attach[0]}" "${param_smart_attach[3]}" "${param_smart_attach[2]}"
}

function agent_parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi

		case $1 in
			--${param_auto_agent[0]}|-${param_auto_agent[0]}|--${param_auto_agent[1]}|-${param_auto_agent[1]})
				shift 1
				agent_auto_agent_enabled=$1
				log $verbose "Param: ${param_auto_agent[0]} = $agent_auto_agent_enabled"
				shift 1
			;;
			--${param_auto_agent[0]}=*|-${param_auto_agent[0]}=*|--${param_auto_agent[1]}=*|-${param_auto_agent[1]}=*)
				agent_auto_agent_enabled=${1#*=}
				log $verbose "Param: ${param_auto_agent[0]} = $agent_auto_agent_enabled"
				shift 1
			;;
			--${param_smart_attach[0]}|-${param_smart_attach[0]}|--${param_smart_attach[1]}|-${param_smart_attach[1]})
				shift 1
				agent_smart_attach_enabled=$1
				log $verbose "Param: ${param_smart_attach[0]} = $agent_smart_attach_enabled"
				shift 1
			;;
			--${param_smart_attach[0]}=*|-${param_smart_attach[0]}=*|--${param_smart_attach[1]}=*|-${param_smart_attach[1]}=*)
				agent_smart_attach_enabled=${1#*=}
				log $verbose "Param: ${param_smart_attach[0]} = $agent_smart_attach_enabled"
				shift 1
			;;
			*)
				shift 1
			;;
		esac
	done
}

function agent_init()
{
	agent_parse_command_line $@
}

function agent_enable_smart_attach()
{
	local service_id=$1
	local backend_url=$2
	local bootstrap_jar=$3
	
	agent_change_smart_attach attach "$service_id" "$backend_url" "$bootstrap_jar"
}

function agent_disable_smart_attach()
{
	local service_id=$1
	local backend_url=$2
	local bootstrap_jar=$3
	
	agent_change_smart_attach detach "$service_id" "$backend_url" "$bootstrap_jar"
}

function agent_change_smart_attach()
{
	local action=$1
	local service_id=$2
	local backend_url=$3
	local bootstrap_jar=$4
	
	local smart_attach_args="-a $action"
	
	if [ -n "$service_id" ]; then
		smart_attach_args="$smart_attach_args -k $service_id"
	fi
	
	if [ -n "$backend_url" ]; then
		smart_attach_args="$smart_attach_args -b $backend_url"
	fi
	
	if log_is_verbose; then
		smart_attach_args="$smart_attach_args -v"
	fi

	java_run -cp $bootstrap_jar m.M smartattach $smart_attach_args
}

function agent_show_attachment_instructions()
{
	local lib_name=$1
	local product_name=$2
	local site_url=$3
	
	if [ "$utils_non_interactive_mode" == "1" ]; then
		return
	fi
	
	local color='\e[1;38;5;208;48;5;232m'
	local arg_color='\e[49;96m'
	local clear_color='\E[00m'
    
	echo ""
	echo -e "Please restart any Java processes you'd like to monitor with this JVM argument:"
	echo -e "${arg_color}>>>>>>> -agentlib:$lib_name <<<<<<<${clear_color}"
	echo -e "${color}Example 1:${clear_color} /usr/bin/java -Xmx128m ${arg_color}-agentlib:$lib_name${clear_color} -jar my-app.jar"
	echo -e "Make sure the ${arg_color}'-agentlib'${clear_color} argument is passed before the main class or '-jar' argument."
	echo ""

	local TOMCAT_DEFAULT_LOC=""

	if [ "$os_distribution_name" = "Ubuntu" ]; then
		TOMCAT_DEFAULT_LOC="/etc/default/tomcat7"
	elif [ "$os_distribution_name" = "Gentoo" ]; then
		TOMCAT_DEFAULT_LOC="/etc/conf.d/tomcat7"
	else # "Redhat" / "SuSE"
		TOMCAT_DEFAULT_LOC="/etc/sysconfig/tomcat7"
	fi

	echo -e "${color}Example 2:${clear_color} Running $product_name with Apache Tomcat: Edit $TOMCAT_DEFAULT_LOC and add the argument to the JAVA_OPTS variable."
	echo -e "e.g. JAVA_OPTS=\"${arg_color}-agentlib:$lib_name${clear_color} -Xmx128m -XX:+UseConcMarkSweepGC\""
	echo ""
	echo "For more information: $site_url"
}

function agent_enable_auto_agent()
{
	local agent_64bit_file=$1
	local agent_32bit_file=$2
	local env_helper_file=$3
	
	dynamic_libs_install_globally "$agent_64bit_file" "$agent_32bit_file"
	
	if [ ! -f $env_helper_file ]; then
		log $warn "$env_helper_file not found."
		return 1
	fi
	
	$env_helper_file uninstall $agent_64bit_file
	$env_helper_file install $agent_64bit_file

	return 0
}

function agent_disable_auto_agent()
{
	local agent_64bit_file=$1
	local env_helper_file=$2
	
	dynamic_libs_replace_globally "lib${overops_lib_name}.so" "$overops_home/lib/lib${overops_lib_name}Empty.so" "$overops_home/lib32/lib${overops_lib_name}.so"
	
	if [ ! -f $env_helper_file ]; then
		log $warn "$env_helper_file not found."
		return 1
	fi
	
	$env_helper_file uninstall $agent_64bit_file
	return 0
}

function agent_show_attach_message()
{
	local product_name=$1
	local overops_home=$2
	local lib_name=$3
	local exe_name=$4
	local overops_name=$5
	
	echo ""
	echo "$product_name will now attach to new Java processes."
	echo ""

	if [ "$utils_non_interactive_mode" == "0" ]; then
		agent_show_restart_java_message "$lib_name" "$exe_name" "$product_name"
	fi

	echo ""
	echo -n "To use in the current shell(s) "

	echo -e '\E[33;40m\033[1m'"run: 'source $overops_home/etc/$overops_name-auto-agent', or restart the shell.\033[0m"
	tput sgr0
}

function agent_show_restart_java_message()
{
	local lib_name=$1
	local exe_name=$2
	local product_name=$3
	
	local unattached_jvm_pids=`java_list_unattached_jvms "$lib_name" "$exe_name"`
	
	if [ ${#unattached_jvm_pids[@]} != 0 ]; then
		local color='\e[1;38;5;208;48;5;232m'
		local link_color='\e[49;96m'
		local arg_color='\e[4m'
		local clear_color='\E[00m'
		
		echo -e "${color}Please restart the following Java processes with the ${arg_color}-agentlib:$lib_name${clear_color}${color} argument:${clear_color}"
		
		echo ""
		java_pretty_print_java_processes "${unattached_jvm_pids[@]}"
		echo ""
		read -t30 -n1 -rsp $'After restarting, press any key to continue.\n' < /dev/tty
		echo ""
		
		local new_unattached_jvm_pids=`java_list_unattached_jvms "$lib_name" "$exe_name"`
		local remaining_unattached_jvm_pids=`utils_array_keep_duplicate "${unattached_jvm_pids[@]}" "${new_unattached_jvm_pids[@]}"`
		
		if [ ${#remaining_unattached_jvm_pids[@]} != 0 ]; then
			echo -e "${color}WARNING:${clear_color} The following Java processes still require a restart with the ${arg_color}-agentlib:$lib_name${clear_color} argument for $product_name to monitor them:"
			echo ""
			print_running_java_processes "${remaining_unattached_jvm_pids[@]}"
		fi
	else
		local color='\e[1;38;5;208;48;5;232m'
		local link_color='\e[49;96m'
		local clear_color='\E[00m'
		echo -e "${color}Please restart any JVMs currently running on your machine${clear_color}"
	fi
}

agent_init $utils_script_params

declare overops_allow_configure_installation_directory="1"


# source logs.sh
# source os.sh

declare -ra param_installation_key=("installation_key" "secret_key" "sk" "" "Specify installation key")
declare -ra param_installation_token=("installation_token" "installation_token" "token" "" "Specify installation token")
declare -ra param_server_name=("server_name" "machine_name" "" "" "Specify server name")
declare -ra param_backend_url=("backend_url" "base_url" "" "" "Specify backend URL")
declare -ra param_storage_test_url=("storage_test_url" "s3_url" "" "" "Specify storage ping URL")
declare -ra param_listen_port=("listen_port" "listen_on_port" "" "" "Specify collector port to listen")
declare -ra param_collector_host=("collector_host" "daemon_host" "" "" "Specify a remote collector host")
declare -ra param_collector_port=("collector_port" "daemon_port" "" "" "Specify a remote collector port")
declare -ra param_tmp_dir=("tmp_dir" "" "" "" "TEMP folder for the installation")
declare -ra param_tmp_dir_minimal_size=("tmp_dir_minimal_size" "" "" "" "TEMP folder minimal free space for the installation (in Bytes)")
declare -ra param_passphrase=("passphrase" "" "" "" "Specify an authentication token between Daemon and Agent")
declare -ra param_installation_dir=("installation_dir" "" "" "" "Specify the installation directory")
declare -ra param_installation_dir_minimal_size=("installation_dir_minimal_size" "" "" "" "Specify the installation directory minimal free space (in Bytes)")
declare -ra param_dry_run=("dry_run" "" "" "" "If set will validate the pre requirements only")
declare -ra param_strict_check=("strict" "" "" "" "Exit on first error or continue all validations")
declare -ra param_unprivileged_mode=("unprivileged" "" "" "Run in unprivileged mode (different user then root)")
declare -ra param_user_name=("user" "" "" "" "Specify the user name")
declare -ra param_user_group=("group" "" "" "" "Specify the user group")
declare -ra param_user_password=("password" "" "" "" "Specify the new user password")
declare -ra param_shutdown_grace_time=("shutdownGraceTime" "" "" "" "Sleep on agent shutdown")
declare -ra param_resource_limit=("resources_size_limit" "resourceFolderLimit" "" "" "Specify the resource folder limit in MB")
declare -ra param_local_collector=("local_collector" "" "" "" "Force local collector")
declare -ra param_t4c_mode=("t4c_mode" "" "" "" "Install/Change both Collector and Agent t4c mode (Internal)")
declare -ra param_non_root=("non_root_wd" "" "" "" "Start collector not as root (don't run as a service")
declare -ra param_work_path=("work_path" "" "" "" "Create the symlink to an external work folder")
declare -ra param_log_path=("log_path" "" "" "" "Create the symlink to an external log folder")

# collector properties
declare -r properties_backend_url="takipi.backend.url"
declare -r properties_installation_time="takipi.installation.time"
declare -r properties_jvm_lib_file="takipi.jvm.lib.file"
declare -r properties_server_name="takipi.server.name"
declare -r properties_storage_test_url="takipi.storage.test.url"
declare -r properties_listen_port="takipi.listen.port"
declare -r properties_passphrase="takipi.passphrase"
declare -r properties_jvm_heap_size="takipi.jvm.heap.size"
declare -r properties_https_proxy="takipi.https.proxy"
declare -r properties_unchained_mode="takipi.unchained"
declare -r properties_handler_threads="takipi.handler.threads"
declare -r properties_handler_clients="takipi.handler.clients"
declare -r properties_disable_ipc="disableIPC"
declare -r properties_encrypt_key="takipi.encrypt.key"
declare -r properties_encrypt="takipi.encrypt"
declare -r properties_encrypt_fast="takipi.encrypt.fast"

# agent properties
declare -r properties_collector_host="takipi.collector.host"
declare -r properties_collector_port="takipi.collector.port"
declare -r properties_collector_passphrase="takipi.collector.passphrase"
declare -r properties_resources_limit="takipi.resources.size.limit"
declare -r properties_short_url_prefix="takipi.short.url.prefix"
declare -r properties_env_id="takipi.env.id"

# common properties
declare -r properties_t4c_mode="takipi.t4c"

declare overops_name="takipi"
declare overops_exe_name="takipi-service"
declare overops_product_name="Takipi"
declare overops_lib_name="TakipiAgent"
declare overops_frontend_url="https://app.$overops_name.com/"
declare overops_site_url="www.$overops_name.com"
declare overops_default_file=""
declare overops_default_daemon_host="localhost"
declare overops_installed="0"
declare overops_secret_key=""
declare overops_installation_token=""
declare overops_service_id=""
declare overops_is_valid_creds="0"
declare overops_machine_name=""
declare overops_max_file_descriptors=""
declare overops_is_aos_mode="0"
declare overops_auto_update_enabled="1"
declare overops_default_user_name="takipi"
declare overops_default_user_group="takipi"
declare overops_default_user_password="takipi"

declare -r overops_collector_config_file_name="collector.properties"
declare -r overops_agent_config_file_name="agent.properties"

# Constants for Collector
declare overops_controller_max_file_descritors="16384"
declare overops_controller_java_heap_size="4G"

# At first sight this place looks like the perfect place to define the default values for 
#  these variable (e.g. overops_backend_url=http://backend.takipi.com). We don't do
#  it since we want to allow the values in 'takipi.properties' to override the default
#  values. When we load 'takipi.properties' at the begining of "overops_init" we can't
#  override existing variables because they may be the values of the command line 
#  arguments.
# Hence, We set the default values of these variables only after we read the command
#  line arguments and read the 'takipi.properties' file. Have a look in "overops_init" 
#  method to see the implementation
#
#
# IMPORTANT: DO NOT SET DEFAULT VALUES HERE, READ ABOVE COMMENT FIRST
#
declare overops_backend_url=""
declare overops_s3_ping_url=""
declare overops_listen_on_port=""
declare overops_daemon_host=""
declare overops_tmp_dir="/tmp"
declare overops_tmp_dir_minimal_size="10240"
declare overops_installation_dir_minimal_size="102400"
declare overops_daemon_port=""
declare overops_aos_passphrase=""
declare overops_java_heap_size=""
declare overops_unchained_mode="false"
declare overops_handler_threads=50
declare overops_handler_clients=20
declare overops_dry_run="0"
declare overops_strict_check="0"
declare overops_priviliged_mode="1"
declare overops_user_name=""
declare overops_user_group=""
declare overops_user_password=""
declare overops_shutdown_grace_time=""
declare overops_resource_limit=""
declare overops_disable_ipc=""
declare overops_t4c_mode=""
declare overops_encrypt_key=""
declare overops_encrypt=""
declare overops_encrypt_fast=""
declare overops_wipe="false"
declare overops_non_root="false"
declare overops_log_path=""
declare overops_work_path=""
declare overops_short_url_prefix=""
declare overops_env_id=""

# These parameters are related the installation directory, We define them after the
#  command line options are evaluated. The installer script define them based on the
#  'installation_dir' parameter while the other script infer it from the script location
#
[ -z "$overops_home" ] && declare overops_home=""
declare overops_bootstrap_jar=""
declare overops_lib_directory=""
declare overops_old_secret_key_file=""
declare overops_installation_key_file=""
declare overops_installation_token_file=""
declare overops_daemon_file=""
declare overops_old_config_file=""
declare overops_collector_config_file=""
declare overops_agent_config_file=""
declare overops_agent_file=""

declare -r overops_no_root_collector_stop_file=".stop-service"

if [ -z "$overops_allow_configure_installation_directory" ]; then
	overops_allow_configure_installation_directory="0"
fi

function overops_usage()
{
	local end_line="\n  "
	
	printf "%-5s %-20s %-70s %s$end_line" "-${param_installation_key[2]}" "--${param_installation_key[0]}" "${param_installation_key[4]}" "${param_installation_key[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "-${param_installation_token[2]}" "--${param_installation_token[0]}" "${param_installation_token[4]}" "${param_installation_token[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_server_name[0]}" "${param_server_name[4]}" "${param_server_name[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_backend_url[0]}" "${param_backend_url[4]}" "${param_backend_url[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_storage_test_url[0]}" "${param_storage_test_url[4]}" "${param_storage_test_url[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_listen_port[0]}" "${param_listen_port[4]}" "${param_listen_port[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_collector_host[0]}" "${param_collector_host[4]}" "${param_collector_host[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_tmp_dir[0]}" "${param_tmp_dir[4]}" "${param_tmp_dir[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_tmp_dir_minimal_size[0]}" "${param_tmp_dir_minimal_size[4]}" "${param_tmp_dir_minimal_size[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_collector_port[0]}" "${param_collector_port[4]}" "${param_collector_port[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_passphrase[0]}" "${param_passphrase[4]}" "${param_passphrase[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_installation_dir[0]}" "${param_installation_dir[4]}" "${param_installation_dir[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_installation_dir_minimal_size[0]}" "${param_installation_dir_minimal_size[4]}" "${param_installation_dir_minimal_size[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_strict_check[0]}" "${param_strict_check[4]}" "${param_strict_check[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_dry_run[0]}" "${param_dry_run[4]}" "${param_dry_run[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_unprivileged_mode[0]}" "${param_unprivileged_mode[3]}" "${param_unprivileged_mode[2]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_user_name[0]}" "${param_user_name[4]}" "${param_user_name[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_user_password[0]}" "${param_user_password[4]}" "${param_user_password[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_user_group[0]}" "${param_user_group[4]}" "${param_user_group[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_shutdown_grace_time[0]}" "${param_shutdown_grace_time[4]}" "${param_shutdown_grace_time[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_resource_limit[0]}" "${param_resource_limit[4]}" "${param_resource_limit[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_local_collector[0]}" "${param_local_collector[4]}" "${param_local_collector[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_work_path[0]}" "${param_work_path[4]}" "${param_work_path[3]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_log_path[0]}" "${param_log_path[4]}" "${param_log_path[3]}"
	
	# lll: Not documented on purpose, we use this parameter internally from tfc-installer & installer-fpm
	#
	# printf "%-5s %-20s %-70s %s$end_line" "" "--${param_t4c_mode[0]}" "${param_t4c_mode[4]}" "${param_t4c_mode[3]}"
}

function overops_parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi
		
	 	case $1 in
	 		--${param_installation_key[0]}|-${param_installation_key[0]}|--${param_installation_key[1]}|-${param_installation_key[1]}|--${param_installation_key[2]}|-${param_installation_key[2]})
				shift 1
				overops_secret_key=$1
				log $verbose "Param: ${param_installation_key[0]} = $overops_secret_key"
				shift 1
			;;
			--${param_installation_key[0]}=*|-${param_installation_key[0]}=*|--${param_installation_key[1]}=*|-${param_installation_key[1]}=*|--${param_installation_key[2]}=*|-${param_installation_key[2]}=*)
				overops_secret_key=${1#*=}
				log $verbose "Param: ${param_installation_key[0]} = $overops_secret_key"
				shift 1
			;;
			--${param_installation_token[0]}|-${param_installation_token[0]}|--${param_installation_token[1]}|-${param_installation_token[1]}|--${param_installation_token[2]}|-${param_installation_token[2]})
				shift 1
				overops_installation_token=$1
				log $verbose "Param: ${param_installation_token[0]} = $overops_installation_token"
				shift 1
			;;
			--${param_installation_token[0]}=*|-${param_installation_token[0]}=*|--${param_installation_token[1]}=*|-${param_installation_token[1]}=*|--${param_installation_token[2]}=*|-${param_installation_token[2]}=*)
				overops_installation_token=${1#*=}
				log $verbose "Param: ${param_installation_token[0]} = $overops_installation_token"
				shift 1
			;;
			--${param_server_name[0]}|-${param_server_name[0]}|--${param_server_name[1]}|-${param_server_name[1]}|--${param_server_name[2]}|-${param_server_name[2]})
				shift 1
				overops_machine_name=$1
				log $verbose "Param: ${param_server_name[0]} = $overops_machine_name"
				shift 1
			;;
			--${param_server_name[0]}=*|-${param_server_name[0]}=*|--${param_server_name[1]}=*|-${param_server_name[1]}=*|--${param_server_name[2]}=*|-${param_server_name[2]}=*)
				overops_machine_name=${1#*=}
				log $verbose "Param: ${param_server_name[0]} = $overops_machine_name"
				shift 1
			;;
			--${param_backend_url[0]}|-${param_backend_url[0]}|--${param_backend_url[1]}|-${param_backend_url[1]}|--${param_backend_url[2]}|-${param_backend_url[2]})
				shift 1
				overops_backend_url=$1
				log $verbose "Param: ${param_backend_url[0]} = $overops_backend_url"
				shift 1
			;;
			--${param_backend_url[0]}=*|-${param_backend_url[0]}=*|--${param_backend_url[1]}=*|-${param_backend_url[1]}=*|--${param_backend_url[2]}=*|-${param_backend_url[2]}=*)
				overops_backend_url=${1#*=}
				log $verbose "Param: ${param_backend_url[0]} = $overops_backend_url"
				shift 1
			;;
			--${param_storage_test_url[0]}|-${param_storage_test_url[0]}|--${param_storage_test_url[1]}|-${param_storage_test_url[1]}|--${param_storage_test_url[2]}|-${param_storage_test_url[2]})
				shift 1
				overops_s3_ping_url=$1
				log $verbose "Param: ${param_storage_test_url[0]} = $overops_s3_ping_url"
				shift 1
			;;
			--${param_storage_test_url[0]}=*|-${param_storage_test_url[0]}=*|--${param_storage_test_url[1]}=*|-${param_storage_test_url[1]}=*|--${param_storage_test_url[2]}=*|-${param_storage_test_url[2]}=*)
				overops_s3_ping_url=${1#*=}
				log $verbose "Param: ${param_storage_test_url[0]} = $overops_s3_ping_url"
				shift 1
			;;
			--${param_listen_port[0]}|-${param_listen_port[0]}|--${param_listen_port[1]}|-${param_listen_port[1]}|--${param_listen_port[2]}|-${param_listen_port[2]})
				shift 1
				overops_listen_on_port=$1
				log $verbose "Param: ${param_listen_port[0]} = $overops_listen_on_port"
				shift 1
			;;
			--${param_listen_port[0]}=*|-${param_listen_port[0]}=*|--${param_listen_port[1]}=*|-${param_listen_port[1]}=*|--${param_listen_port[2]}=*|-${param_listen_port[2]}=*)
				overops_listen_on_port=${1#*=}
				log $verbose "Param: ${param_listen_port[0]} = $overops_listen_on_port"
				shift 1
			;;
			--${param_collector_host[0]}|-${param_collector_host[0]}|--${param_collector_host[1]}|-${param_collector_host[1]}|--${param_collector_host[2]}|-${param_collector_host[2]})
				shift 1
				overops_daemon_host=$1
				log $verbose "Param: ${param_collector_host[0]} = $overops_daemon_host"
				shift 1
			;;
			--${param_collector_host[0]}=*|-${param_collector_host[0]}=*|--${param_collector_host[1]}=*|-${param_collector_host[1]}=*|--${param_collector_host[2]}=*|-${param_collector_host[2]}=*)
				overops_daemon_host=${1#*=}
				log $verbose "Param: ${param_collector_host[0]} = $overops_daemon_host"
				shift 1
			;;
			--${param_collector_port[0]}|-${param_collector_port[0]}|--${param_collector_port[1]}|-${param_collector_port[1]}|--${param_collector_port[2]}|-${param_collector_port[2]})
				shift 1
				overops_daemon_port=$1
				log $verbose "Param: ${param_collector_port[0]} = $overops_daemon_port"
				shift 1
			;;
			--${param_collector_port[0]}=*|-${param_collector_port[0]}=*|--${param_collector_port[1]}=*|-${param_collector_port[1]}=*|--${param_collector_port[2]}=*|-${param_collector_port[2]}=*)
				overops_daemon_port=${1#*=}
				log $verbose "Param: ${param_collector_port[0]} = $overops_daemon_port"
				shift 1
			;;
			--${param_tmp_dir[0]}|-${param_tmp_dir[0]}|--${param_tmp_dir[2]}|-${param_tmp_dir[2]})
				shift 1
				overops_tmp_dir=$1
				log $verbose "Param: ${param_tmp_dir[0]} = $overops_tmp_dir"
				shift 1
			;;
			--${param_tmp_dir[0]}=*|-${param_tmp_dir[0]}=*|--${param_tmp_dir[2]}=*|-${param_tmp_dir[2]}=*)
				overops_tmp_dir=${1#*=}
				log $verbose "Param: ${param_tmp_dir[0]} = $overops_tmp_dir"
				shift 1
			;;
			--${param_tmp_dir_minimal_size[0]}|-${param_tmp_dir_minimal_size[0]}|--${param_tmp_dir_minimal_size[2]}|-${param_tmp_dir_minimal_size[2]})
				shift 1
				overops_tmp_dir_minimal_size=$1
				log $verbose "Param: ${param_tmp_dir_minimal_size[0]} = $overops_tmp_dir_minimal_size"
				shift 1
			;;
			--${param_tmp_dir_minimal_size[0]}=*|-${param_tmp_dir_minimal_size[0]}=*|--${param_tmp_dir_minimal_size[2]}=*|-${param_tmp_dir_minimal_size[2]}=*)
				overops_tmp_dir_minimal_size=${1#*=}
				log $verbose "Param: ${param_tmp_dir_minimal_size[0]} = $overops_tmp_dir_minimal_size"
				shift 1
			;;
			--${param_installation_dir_minimal_size[0]}|-${param_installation_dir_minimal_size[0]}|--${param_installation_dir_minimal_size[2]}|-${param_installation_dir_minimal_size[2]})
				shift 1
				overops_installation_dir_minimal_size=$1
				log $verbose "Param: ${param_installation_dir_minimal_size[0]} = $overops_installation_dir_minimal_size"
				shift 1
			;;
			--${param_installation_dir_minimal_size[0]}=*|-${param_installation_dir_minimal_size[0]}=*|--${param_installation_dir_minimal_size[2]}=*|-${param_installation_dir_minimal_size[2]}=*)
				overops_installation_dir_minimal_size=${1#*=}
				log $verbose "Param: ${param_installation_dir_minimal_size[0]} = $overops_installation_dir_minimal_size"
				shift 1
			;;
			--${param_passphrase[0]}|-${param_passphrase[0]}|--${param_passphrase[2]}|-${param_passphrase[2]})
				shift 1
				overops_aos_passphrase=$1
				log $verbose "Param: ${param_passphrase[0]} = $overops_aos_passphrase"
				shift 1
			;;
			--${param_passphrase[0]}=*|-${param_passphrase[0]}=*|--${param_passphrase[2]}=*|-${param_passphrase[2]}=*)
				overops_aos_passphrase=${1#*=}
				log $verbose "Param: ${param_passphrase[0]} = $overops_aos_passphrase"
				shift 1
			;;
			--${param_user_name[0]}|-${param_user_name[0]}|--${param_user_name[2]}|-${param_user_name[2]})
				shift 1
				overops_user_name=$1
				log $verbose "Param: ${param_user_name[0]} = $overops_user_name"
				shift 1
			;;
			--${param_user_name[0]}=*|-${param_user_name[0]}=*|--${param_user_name[2]}=*|-${param_user_name[2]}=*)
				overops_user_name=${1#*=}
				log $verbose "Param: ${param_user_name[0]} = $overops_user_name"
				shift 1
			;;
			--${param_user_group[0]}|-${param_user_group[0]}|--${param_user_group[2]}|-${param_user_group[2]})
				shift 1
				overops_user_group=$1
				log $verbose "Param: ${param_user_group[0]} = $overops_user_group"
				shift 1
			;;
			--${param_user_group[0]}=*|-${param_user_group[0]}=*|--${param_user_group[2]}=*|-${param_user_group[2]}=*)
				overops_user_group=${1#*=}
				log $verbose "Param: ${param_user_group[0]} = $overops_user_group"
				shift 1
			;;
			--${param_user_password[0]}|-${param_user_password[0]}|--${param_user_password[2]}|-${param_user_password[2]})
				shift 1
				overops_user_password=$1
				log $verbose "Param: ${param_user_password[0]} = $overops_user_password"
				shift 1
			;;
			--${param_user_password[0]}=*|-${param_user_password[0]}=*|--${param_user_password[2]}=*|-${param_user_password[2]}=*)
				overops_user_password=${1#*=}
				log $verbose "Param: ${param_user_password[0]} = $overops_user_password"
				shift 1
			;;
			--${param_installation_dir[0]}|-${param_installation_dir[0]}|--${param_installation_dir[2]}|-${param_installation_dir[2]})
				shift 1
				overops_home=$1
				log $verbose "Param: ${param_installation_dir[0]} = $overops_home"
				shift 1
			;;
			--${param_installation_dir[0]}=*|-${param_installation_dir[0]}=*|--${param_installation_dir[2]}=*|-${param_installation_dir[2]}=*)
				overops_home=${1#*=}
				log $verbose "Param: ${param_installation_dir[0]} = $overops_home"
				shift 1
			;;
	    	--${param_dry_run[0]}|-${param_dry_run[0]}|--${param_dry_run[2]}|-${param_dry_run[2]})
				overops_dry_run="1"
				log $verbose "Param: ${param_dry_run[0]} = true"
				shift 1
			;;
    		--${param_strict_check[0]}|-${param_strict_check[0]}|--${param_strict_check[2]}|-${param_strict_check[2]})
				overops_strict_check="1"
				log $verbose "Param: ${param_strict_check[0]} = true"
				shift 1
			;;
			--${param_unprivileged_mode[0]}|-${param_unprivileged_mode[0]}|--${param_unprivileged_mode[1]}|-${param_unprivileged_mode[1]})
				overops_priviliged_mode="0"
				log $verbose "Param: ${param_unprivileged_mode[0]} = true"
				shift 1
			;;
			--${param_shutdown_grace_time[0]}|-${param_shutdown_grace_time[0]}|--${param_shutdown_grace_time[2]}|-${param_shutdown_grace_time[2]})
				shift 1
				overops_shutdown_grace_time=$1
				log $verbose "Param: ${param_shutdown_grace_time[0]} = $overops_shutdown_grace_time"
				shift 1
			;;
			--${param_shutdown_grace_time[0]}=*|-${param_shutdown_grace_time[0]}=*|--${param_shutdown_grace_time[2]}=*|-${param_shutdown_grace_time[2]}=*)
				overops_shutdown_grace_time=${1#*=}
				log $verbose "Param: ${param_shutdown_grace_time[0]} = $overops_shutdown_grace_time"
				shift 1
			;;
			--${param_resource_limit[0]}|-${param_resource_limit[0]}|--${param_resource_limit[1]}|-${param_resource_limit[1]}|--${param_resource_limit[2]}|-${param_resource_limit[2]})
				shift 1
				overops_resource_limit=$1
				log $verbose "Param: ${param_resource_limit[0]} = $overops_resource_limit"
				shift 1
			;;
			--${param_resource_limit[0]}=*|-${param_resource_limit[0]}=*|--${param_resource_limit[1]}=*|-${param_resource_limit[1]}=*|--${param_resource_limit[2]}=*|-${param_resource_limit[2]}=*)
				overops_resource_limit=${1#*=}
				log $verbose "Param: ${param_resource_limit[0]} = $overops_resource_limit"
				shift 1
			;;
			--${param_local_collector[0]}|-${param_local_collector[0]}|--${param_local_collector[2]}|-${param_local_collector[2]})
				overops_disable_ipc="false"
				log $verbose "Param: ${param_local_collector[0]} = true"
				shift 1
			;;
			--${param_t4c_mode[0]}|-${param_t4c_mode[0]}|--${param_t4c_mode[2]}|-${param_t4c_mode[2]})
				overops_t4c_mode="true"
				log $verbose "Param: ${param_t4c_mode[0]} = true"
				shift 1
			;;
			--${param_work_path[0]}|-${param_work_path[0]}|--${param_work_path[1]}|-${param_work_path[1]}|--${param_work_path[2]}|-${param_work_path[2]})
				shift 1
				overops_work_path=$1
				log $verbose "Param: ${param_work_path[0]} = $overops_work_path"
				shift 1
			;;
			--${param_work_path[0]}=*|-${param_work_path[0]}=*|--${param_work_path[1]}=*|-${param_work_path[1]}=*|--${param_work_path[2]}=*|-${param_work_path[2]}=*)
				overops_work_path=${1#*=}
				log $verbose "Param: ${param_work_path[0]} = $overops_work_path"
				shift 1
			;;
			--${param_log_path[0]}|-${param_log_path[0]}|--${param_log_path[1]}|-${param_log_path[1]}|--${param_log_path[2]}|-${param_log_path[2]})
				shift 1
				overops_log_path=$1
				log $verbose "Param: ${param_log_path[0]} = $overops_log_path"
				shift 1
			;;
			--${param_log_path[0]}=*|-${param_log_path[0]}=*|--${param_log_path[1]}=*|-${param_log_path[1]}=*|--${param_log_path[2]}=*|-${param_log_path[2]}=*)
				overops_log_path=${1#*=}
				log $verbose "Param: ${param_log_path[0]} = $overops_log_path"
				shift 1
			;;
			--${param_non_root[0]}|-${param_non_root[0]}|--${param_non_root[2]}|-${param_non_root[2]})
                                overops_non_root="true"
                                log $verbose "Param: ${param_non_root[0]} = true"
                                shift 1
                        ;;			
			*)
				shift 1
			;;
		esac
	done
}

function overops_init()
{
	overops_load_default_file
	
	overops_parse_command_line $@
	overops_configure_installation_directory
	
	if [ -r "$overops_old_config_file"  ]; then
		overops_migrate_config_file "$overops_old_config_file" "0"
	fi

	if [ -r "$overops_old_secret_key_file"  ]; then
		overops_migrate_secret_key "$overops_old_secret_key_file"
	fi
	
	if [ -r "$overops_agent_config_file" ] || [ -r "$overops_collector_config_file" ]; then
		overops_load_config_file "0"
		overops_installed="1"
	fi
	
	if [ -z "$overops_backend_url" ]; then
		overops_backend_url="https://backend.overops.com/"
	fi
	
	if [ -z "$overops_s3_ping_url" ]; then
		log $verbose "Setting storage ping URL with backend url: $overops_backend_url"

		case $overops_backend_url in 
			*.takipi.com | *.takipi.net | *.overops.com | *.takipi.com/ | *.takipi.net/ | *.overops.com/)
				overops_s3_ping_url="https://s3.amazonaws.com/app-takipi-com/ConnectionTest"
				;;
			*)
				overops_s3_ping_url="$overops_backend_url/service/png"
				;;
		esac
	fi
	
	if [ -z "$overops_secret_key" -a -r "$overops_installation_key_file" ]; then
		overops_secret_key=`cat $overops_installation_key_file` >/dev/null 2>&1
	fi
	
	if [ -z "$overops_installation_token" -a -r "$overops_installation_token_file" ]; then
		overops_installation_token=`cat $overops_installation_token_file` >/dev/null 2>&1
	fi
	
	if [ -z "$overops_disable_ipc" ]; then
		overops_disable_ipc="true"
	fi
	
	if [ -z "$overops_t4c_mode" ]; then
		overops_t4c_mode="false"
	fi
	
	if [ -n "$overops_secret_key" ]; then
		overops_service_id=(${overops_secret_key//#/ })
		echo "$overops_secret_key" | grep "^S[1-9][0-9]*#[^#][^#]*#[^#][^#]*#[0-9A-Fa-f]\{4\}$" > /dev/null 2>&1
		
		if [ $? -eq 0 ]; then
			overops_is_valid_creds="1"
		fi
	elif [ -n "$overops_installation_token" ]; then
		overops_is_valid_creds="1"
	fi
	
	if [ -n "$overops_secret_key" -a -n "$overops_installation_token" ]; then
		log $warn "Both installation key and token provided. Token will be used."
	fi
	
	# Enable default standalone agent mode only if:
	#	1. We got an address to a remote Collector
	#	2. No explicit port specified for this Collector
	#	3. This mode is allowd by overops_prevent_aos_mode
	#
	if [ -n "$overops_daemon_host" -a -n "$overops_daemon_port" -a -z "$overops_listen_on_port" ]; then
		if [ "$overops_prevent_aos_mode" != "1" ]; then
			overops_is_aos_mode="1"
		fi
	fi
	
	# Enable default remote collector mode only if:
	#	1. ipc is disabled
	#	2. it is not a standalone agent
	#
	if [ "$overops_is_aos_mode" == "0" -a "$overops_disable_ipc" == "true" ]; then
		if [ -z "$overops_listen_on_port" ]; then
			overops_listen_on_port="6060"
		fi
	fi
	
	if [ -n "$overops_listen_on_port" -a -z "$overops_java_heap_size" ]; then
		overops_java_heap_size="$overops_controller_java_heap_size"
	fi

	if [ -n "$overops_listen_on_port" ]; then
		overops_max_file_descriptors="$overops_controller_max_file_descritors"
		overops_unchained_mode="true"

		if [ "$overops_disable_ipc" == "true" ]; then
			[ -z "$overops_daemon_host" ] && overops_daemon_host="$overops_default_daemon_host"
			[ -z "$overops_daemon_port" ] && overops_daemon_port="$overops_listen_on_port"
		fi
	fi

	if [ "$overops_priviliged_mode" == "0" ]; then
		[ -n "$overops_user_name" ] || overops_user_name="$overops_default_user_name"
		[ -n "$overops_user_password" ] || overops_user_password="$overops_default_user_password"
		[ -n "$overops_user_group" ] || overops_user_group="$overops_default_user_group"
		
		log $verbose "Installing as user: $overops_user_name and group $overops_user_group"
	else
		overops_user_name="$os_root_user_name"
		overops_user_password="$os_root_user_password"
		overops_user_group="$os_root_user_group"
	fi

	report_init "$overops_backend_url" "$overops_service_id"
	
	log $verbose "Takipi initialized in $overops_home (sid: $overops_service_id) (installed? $overops_installed)"
}

function overops_can_run_installation()
{
	local iserror=0

	if [ "$os_is_sudo" != "1" ]; then
		log $error "You need root privileges to run this script."
		report_status 4
		iserror=1

		[ "X$overops_strict_check" == "X1" ] || return 1
	fi
	
	if [ "$os_machine_architecture" != 'x86_64' ]; then
		log $error "$overops_product_name is only supported on 64-bit platforms."
		log $error "Canceling installation."
		report_status 5
		iserror=1

		[ "X$overops_strict_check" == "X1" ] && return 1
	fi
	
	if ! network_can_download; then
		log $error "Cannot find wget or curl."
		log $error "Please install either wget or curl, and restart the installation."
		iserror=1

		[ "X$overops_strict_check" == "X1" ] && return 1
	fi
	
	if [ -n $overops_listen_on_port ]; then
		if network_is_port_used "$overops_listen_on_port" "$(pidof takipi-service)"; then
			log $error "The following ports are taken: $overops_listen_on_port"
			iserror=1

			[ "X$overops_strict_check" == "X1" ] && return 1
		fi
	fi

	if [ "$overops_is_aos_mode" == "0" ]; then
		if [ ! -d "/dev/shm" ]; then
			log $error "cant find /dev/shm directory"
			iserror=1

			[ "X$overops_strict_check" == "X1" ] && return 1
		fi
	fi

	if ! java_found_valid_java; then
		java_show_invalid_java_message "$overops_product_name"
		iserror=1

		[ "X$overops_strict_check" == "X1" ] && return 1
	fi
	
	if ! os_get_free_space_by_path $overops_tmp_dir $overops_tmp_dir_minimal_size; then
		local tmp_dir_free_space=$(os_get_free_space_in_bytes_by_path $overops_tmp_dir)
		log $error "Not enough free disk space in $overops_tmp_dir, found $(( $tmp_dir_free_space / 1024 ))MB while Expecting $(( $overops_tmp_dir_minimal_size / 1024 ))MB of free space"
		iserror=1

		[ "X$overops_strict_check" == "X1" ] && return 1
	fi

	if ! os_get_free_space_by_path $overops_home $overops_installation_dir_minimal_size; then
		local installation_dir_free_space=$(os_get_free_space_in_bytes_by_path $overops_home)
		log $error "Not enough free disk space in $overops_home, found $(( $installation_dir_free_space / 1024 ))MB while Expecting $(( $overops_installation_dir_minimal_size / 1024 )) MB of free space"
		iserror=1

		[ "X$overops_strict_check" == "X1" ] && return 1
	fi
	
	return $iserror
}

function overops_configure_installation_directory()
{
	# Probably only the installer script allows to configure the installation directory 
	#
	if [ "$overops_allow_configure_installation_directory" == "1" ]; then
		if [ -z "$overops_home" ]; then
			overops_home="/opt"
		fi
		
		# This is to make sure we end up with a something/takipi folder structure
		case $overops_home in
			*/$overops_name) 
				overops_home=$overops_home
				;;
			*) 
				overops_home=$overops_home/$overops_name
				;;
		esac
	else
		overops_home=`dirname $utils_script_dir`
	fi
	
	overops_bootstrap_jar="$overops_home/jars/takipi-bootstrap.jar"
	overops_lib_directory="$overops_home/lib"
	overops_old_secret_key_file="$overops_home/work/secret.key"
	overops_installation_key_file="$overops_home/installation.key"
	overops_installation_token_file="$overops_home/installation.token"
	overops_daemon_file="$overops_home/bin/$overops_exe_name"
	overops_old_config_file="$overops_home/$overops_name.properties"
	overops_collector_config_file="$overops_home/$overops_collector_config_file_name"
	overops_agent_config_file="$overops_home/$overops_agent_config_file_name"
	overops_agent_file="$overops_lib_directory/lib$overops_lib_name.so"
}

function overops_migrate_config_file()
{
	local file_to_migrate=$1
	local should_override=$2

	eval "$(utils_replace_underscore_with_dots $file_to_migrate)"

	[ -n "$libraryPath" ] && overops_lib_directory=$libraryPath
	[ -n "$autoUpdate" ] && overops_auto_update_enabled=$autoUpdate
	[ -n "$serviceId" ] && overops_service_id=$serviceId

	if [ -z "$overops_user_name" -o $should_override == "1" ]; then
		[ -n "$userName" ] && overops_user_name=$userName
	fi

	if [ -z "$overops_shutdown_grace_time" -o $should_override == "1" ]; then
		[ -n "$shutdownGraceTime" ] && overops_shutdown_grace_time=$shutdownGraceTime
	fi

	if [ -z "$overops_backend_url" -o $should_override == "1" ]; then
		[ -n "$baseUrl" ] && overops_backend_url=$baseUrl
		[ -n "$takipi_backend_url" ] && overops_backend_url=$takipi_backend_url
	fi
	
	[ -n "$jvmPath" ] && java_jvm_lib_file=$jvmPath
	[ -n "$takipi_jvm_lib_file" ] && java_jvm_lib_file=$takipi_jvm_lib_file

	if [ -z "$overops_machine_name" -o $should_override == "1" ]; then
		[ -n "$serverName" ] && overops_machine_name=$serverName
		[ -n "$takipi_server_name" ] && overops_machine_name=$takipi_server_name
	fi

	[ -n "$httpsProxy" ] && network_set_proxy "$httpsProxy"
	[ -n "$takipi_https_proxy" ] && network_set_proxy "$takipi_https_proxy"

	if [ -z "$overops_s3_ping_url" -o $should_override == "1" ]; then
		[ -n "$s3ConnectionTestUrl" ] && overops_s3_ping_url=$s3ConnectionTestUrl
		[ -n "$takipi_storage_test_url" ] && overops_s3_ping_url=$takipi_storage_test_url
	fi

	if [ -z "$overops_listen_on_port" -o $should_override == "1" ]; then
		[ -n "$listenOnPort" ] && overops_listen_on_port=$listenOnPort
		[ -n "$takipi_listen_port" ] && overops_listen_on_port=$takipi_listen_port
	fi

	if [ -z "$overops_daemon_host" -o $should_override == "1" ]; then
		[ -n "$masterHost" ] && overops_daemon_host=$masterHost
		[ -n "$takipi_collector_host" ] && overops_daemon_host=$takipi_collector_host
	fi

	if [ -z "$overops_daemon_port" -o $should_override == "1" ]; then
		[ -n "$masterPort" ] && overops_daemon_port=$masterPort
		[ -n "$takipi_collector_port" ] && overops_daemon_port=$takipi_collector_port
	fi

	if [ -z "$overops_aos_passphrase" -o $should_override == "1" ]; then
		[ -n "$passphrase" ] && overops_aos_passphrase=$passphrase
		[ -n "$takipi_passphrase" ] && overops_aos_passphrase=$takipi_passphrase
	fi

	[ -n "$javaHeapSize" ] && overops_java_heap_size=$javaHeapSize
	[ -n "$takipi_jvm_heap_size" ] && overops_java_heap_size=$takipi_jvm_heap_size

	if [ -z "$overops_resource_limit" -o $should_override == "1" ]; then
		[ -n "$resourceFolderLimit" ] && overops_resource_limit=$resourceFolderLimit
		[ -n "$takipi_resources_size_limit" ] && overops_resource_limit=$takipi_resources_size_limit
	fi

	overops_save_config_file

	echo "Successfully migrated config files"

	mv $file_to_migrate "${file_to_migrate}.old"
}

function overops_migrate_secret_key()
{
	local file_to_migrate=$1

	if [ -s $overops_installation_key_file ]; then
		mv $file_to_migrate "${file_to_migrate}.old"
	else
		cp $file_to_migrate "${file_to_migrate}.old"
		mv $file_to_migrate $overops_installation_key_file
	fi

	echo "Successfully migrated secret key"
}

function overops_load_default_file()
{		
	log $verbose "looking for default file in $os_default_configuration_dir."
	
	if [ -n "$os_default_configuration_dir" ]; then
		overops_default_file="$os_default_configuration_dir/$overops_name"
	fi
	
	if [ -z "$overops_default_file" ]; then
		return
	fi
	
	if [ -r "$overops_default_file" ]; then
		source "$overops_default_file"
	fi
	
	[ -n "$TAKIPI_HOME" ] && overops_home=$TAKIPI_HOME
	[ -n "$TAKIPI_LOG_FOLDER" ] && overops_log_path=$TAKIPI_LOG_FOLDER
	[ -n "$TAKIPI_SERVER_NAME" ] && overops_machine_name=$TAKIPI_SERVER_NAME
	
	# Only for Collector
	[ -n "$TAKIPI_WORK_FOLDER" ] && overops_work_path=$TAKIPI_WORK_FOLDER
	[ -n "$TAKIPI_INSTALLATION_TOKEN" ] && overops_installation_token=$TAKIPI_INSTALLATION_TOKEN
	[ -n "$TAKIPI_INSTALLATION_KEY" ] && overops_secret_key=$TAKIPI_INSTALLATION_KEY
	[ -n "$TAKIPI_BACKEND_URL" ] && overops_backend_url=$TAKIPI_BACKEND_URL
	[ -n "$TAKIPI_LISTEN_PORT" ] && overops_listen_on_port=$TAKIPI_LISTEN_PORT
	
	# Setting these turn it into an agent installation
	[ -n "$TAKIPI_COLLECTOR_HOST" ] && overops_daemon_host=$TAKIPI_COLLECTOR_HOST
	[ -n "$TAKIPI_COLLECTOR_PORT" ] && overops_daemon_port=$TAKIPI_COLLECTOR_PORT

	if [ -n "$TAKIPI_USER_NAME" ]; then
		 overops_priviliged_mode="0"
		 overops_user_name=$TAKIPI_USER_NAME
		 
		 if [ -n "$TAKIPI_USER_GROUP" ]; then
			 overops_user_group=$TAKIPI_USER_GROUP
		 else
			 overops_user_group=$TAKIPI_USER_NAME
		 fi
	fi
}

function overops_save_default_file()
{
	# if [ ! -w $overops_default_file ]; then
	# 	log $error "unable to write $overops_config_file please check permissions.."
	# 	return 1
	# fi
	
	log $verbose "no need to save default file ever"
	return

	if [ -z "$overops_default_file" ]; then
		return
	fi
	
	if [ "$overops_is_aos_mode" == "1" ]; then
		return
	fi

	local proxy=""

	if [ "$network_https_proxy" != "" ]; then
		proxy="TAKIPI_HTTPS_PROXY=$network_https_proxy"
	fi

# The echo lines are not indented on purpose 
	echo \
"TAKIPI_HOME=$overops_home" $'\n'\
"TAKIPI_BASE_URL=$overops_backend_url" $'\n'\
"TAKIPI_NATIVE_LIBRARIES=$overops_lib_directory" $'\n'\
"DAEMON=$overops_daemon_file" $'\n'\
"TAKIPI_INSTALLATION_TIME=$(($(date +%s%N)/1000))" $'\n'\
"JVM_LIB_FILE=$java_jvm_lib_file" $'\n'\
"TAKIPI_MACHINE_NAME=$overops_machine_name" $'\n'\
"$proxy" $'\n'\
> $overops_default_file
}

function overops_load_config_file()
{
	local should_override=$1
	
	# [EEE 27.2.18] the new config files use . for variable names, and cannot be parsed on bash, so we replace with _

	if [ -r "$overops_collector_config_file" ]; then
		eval "$(utils_replace_underscore_with_dots $overops_collector_config_file)"
	fi

	if [ -r "$overops_agent_config_file" ]; then
		eval "$(utils_replace_underscore_with_dots $overops_agent_config_file)"
	fi

	[ -z "$overops_backend_url" -o $should_override == "1" ] && overops_backend_url=$takipi_backend_url
	[ -z "$overops_lib_directory" -o $should_override == "1" ] && overops_lib_directory=$libraryPath
	[ -z "$java_jvm_lib_file" -o $should_override == "1" ] && java_jvm_lib_file=$takipi_jvm_lib_file
	[ -z "$overops_machine_name" -o $should_override == "1" ] && overops_machine_name=$takipi_server_name
	[ -z "$network_https_proxy" -o $should_override == "1" ] && network_set_proxy "$takipi_https_proxy"
	[ -z "$overops_auto_update_enabled" -o $should_override == "1" ] && overops_auto_update_enabled=$autoUpdate
	[ -z "$overops_service_id" -o $should_override == "1" ] && overops_service_id=$serviceId
	[ -z "$overops_s3_ping_url" -o $should_override == "1" ] && overops_s3_ping_url=$takipi_storage_test_url
	[ -z "$overops_listen_on_port" -o $should_override == "1" ] && overops_listen_on_port=$takipi_listen_port
	[ -z "$overops_daemon_host" -o $should_override == "1" ] && overops_daemon_host=$takipi_collector_host
	[ -z "$overops_daemon_port" -o $should_override == "1" ] && overops_daemon_port=$takipi_collector_port
	[ -z "$overops_aos_passphrase" -o $should_override == "1" ] && overops_aos_passphrase=$takipi_passphrase
	[ -z "$overops_java_heap_size" -o $should_override == "1" ] && overops_java_heap_size=$takipi_jvm_heap_size
	[ -z "$overops_user_name" -o $should_override == "1" ] && overops_user_name=$userName
	[ -z "$overops_shutdown_grace_time" -o $should_override == "1" ] && overops_shutdown_grace_time=$shutdownGraceTime
	[ -z "$overops_resource_limit" -o $should_override == "1" ] && overops_resource_limit=$takipi_resources_size_limit
	[ -z "$overops_unchained_mode" -o $should_override == "1" ] && overops_unchained_mode=$takipi_unchained
	[ -z "$overops_handler_threads" -o $should_override == "1" ] && overops_handler_threads=$takipi_handler_threads
	[ -z "$overops_handler_clients" -o $should_override == "1" ] && overops_handler_clients=$takipi_handler_clients
	[ -z "$overops_disable_ipc" -o $should_override == "1" ] && overops_disable_ipc=$disableIPC
	[ -z "$overops_t4c_mode" -o $should_override == "1" ] && overops_t4c_mode=$takipi_t4c
	[ -z "$overops_encrypt_key" -o $should_override == "1" ] && overops_encrypt_key=$takipi_encrypt_key
	[ -z "$overops_encrypt" -o $should_override == "1" ] && overops_encrypt=$takipi_encrypt
	[ -z "$overops_encrypt_fast" -o $should_override == "1" ] && overops_encrypt_fast=$takipi_encrypt_fast
	[ -z "$overops_short_url_prefix" -o $should_override == "1" ] && overops_short_url_prefix=$takipi_short_url_prefix
	[ -z "$overops_env_id" -o $should_override == "1" ] && overops_env_id=$takipi_env_id
}

function overops_save_config_file()
{
	local proxy=""

	# if [ ! -w $overops_config_file ]; then
	# 	log $error "unable to write $overops_config_file please check permissions.."
	# 	return 1
	# fi

	if [ "$network_https_proxy" != "" ]; then
		proxy="$properties_https_proxy=$network_https_proxy"
	fi
	
	local encrypt_key=""
	
	if [ "$overops_encrypt_key" != "" ]; then
		encrypt_key="$properties_encrypt_key=\"$overops_encrypt_key\"" 
	fi
	
	local encrypt=""
	
	if [ "$overops_encrypt" != "" ]; then
		encrypt="$properties_encrypt=$overops_encrypt"
	fi
	
	local encrypt_fast=""
	
	if [ "$overops_encrypt_fast" != "" ]; then
		encrypt_fast="$properties_encrypt_fast=$overops_encrypt_fast"
	fi

	local short_url_prefix=""

	if [ "$overops_short_url_prefix" != "" ]; then
		short_url_prefix="$properties_short_url_prefix=$overops_short_url_prefix"
	fi

	local env_id=""

	if [ "$overops_env_id" != "" ]; then
		env_id="$properties_env_id=$overops_env_id"
	fi

	
# The echo lines are not indented on purpose 

# The following properties are not yet decided on or not relevant anymore: takipiHome, shutdownGraceTime (OO-1395)
	echo \
"takipiHome=$overops_home" $'\n'\
"$properties_collector_host=$overops_daemon_host" $'\n'\
"$properties_collector_port=$overops_daemon_port" $'\n'\
"$properties_collector_passphrase=$overops_aos_passphrase" $'\n'\
"shutdownGraceTime=$overops_shutdown_grace_time" $'\n'\
"$properties_resources_limit=$overops_resource_limit" $'\n'\
"$properties_t4c_mode=$overops_t4c_mode" $'\n'\
"$short_url_prefix" $'\n'\
"$env_id" $'\n'\
"$encrypt_key" $'\n'\
"$encrypt" $'\n'\
"$encrypt_fast" $'\n'\
> $overops_agent_config_file

# The following properties are not yet decided on or not relevant anymore: libraryPath, autoUpdate, serviceId, userName (OO-1395)
	if [ "$overops_is_aos_mode" == "0" ]; then
	echo \
"$properties_backend_url=$overops_backend_url" $'\n'\
"libraryPath=$overops_lib_directory" $'\n'\
"$properties_installation_time=$(($(date +%s%N)/1000))" $'\n'\
"$properties_jvm_lib_file=$java_jvm_lib_file" $'\n'\
"$properties_server_name=$overops_machine_name" $'\n'\
"autoUpdate=$overops_auto_update_enabled" $'\n'\
"serviceId=$overops_service_id" $'\n'\
"$properties_storage_test_url=$overops_s3_ping_url" $'\n'\
"$properties_listen_port=$overops_listen_on_port" $'\n'\
"$properties_unchained_mode=$overops_unchained_mode" $'\n'\
"$properties_handler_threads=$overops_handler_threads" $'\n'\
"$properties_handler_clients=$overops_handler_clients" $'\n'\
"$properties_passphrase=$overops_aos_passphrase" $'\n'\
"$properties_jvm_heap_size=$overops_java_heap_size" $'\n'\
"userName=$overops_user_name" $'\n'\
"$properties_t4c_mode=$overops_t4c_mode" $'\n'\
"$properties_disable_ipc=$overops_disable_ipc" $'\n'\
"$proxy" $'\n'\
"$encrypt_key" $'\n'\
"$encrypt" $'\n'\
"$encrypt_fast" $'\n'\
> $overops_collector_config_file
	else
		echo "$properties_server_name=$overops_machine_name" $'\n' >> $overops_agent_config_file
	fi
}

function overops_export_daemon_envs()
{
	export TAKIPI_HOME=$overops_home
	export TAKIPI_BASE_URL=$overops_backend_url
	export TAKIPI_NATIVE_LIBRARIES=$overops_lib_directory
	export JVM_LIB_FILE=$java_jvm_lib_file
	export DAEMON=$overops_daemon_file
}

function overops_prepare_directories()
{
	if ! overops_create_directory "work" "$overops_home/work" "$overops_work_path"; then
		return 1
	fi
	
	if ! overops_create_directory "log" "$overops_home/log" "$overops_log_path"; then
		return 1
	fi
	
	mkdir -p "$overops_home/log/agents"
	
	return 0
}

# Create a symbolic link directory_path if provided_directory_path exits, 
# else we create directory from directory_path
function overops_create_directory()
{
	local readable_name=$1
	local directory_path=$2
	local provided_directory_path=$3
	
	if [ -z "$directory_path" ]; then
		log $error "Unable to create $readable_name directory, missing path"
		return 1
	fi
	
	if [ -e "$directory_path" -o -h "$directory_path" ]; then
		if [ -n "$provided_directory_path" ]; then
			if [ "$(readlink -f $directory_path)" = $provided_directory_path ]; then
				return 0
			fi
			
			if [ -d $directory_path ]; then
				if find "$directory_path" -type f -print -quit | grep -q '^'; then
					log $error "$readable_name directory already exists at $directory_path, but asked to be in: $provided_directory_path"
					log $error "Please move it manually and try again."
					return 1
				else
					rm -rf $directory_path
				fi
			fi
		fi
	fi
	
	if [ -e "$directory_path" ]; then
		return 0
	fi
	
	if [ -z "$provided_directory_path" ]; then
		log $info "Creating $readable_name directory at $directory_path"
		
		if ! mkdir "$directory_path"; then
			log $error "Unable to create $readable_name directory at: $directory_path"
			return 1
		fi
		
		return 0
	fi
	
	log $info "Linking $readable_name directory to $provided_directory_path"
	
	if ! ln -s $provided_directory_path $directory_path; then
		log $error "Unable to link $provided_directory_path to $directory_path"
		return 1
	fi
	
	return 0
} 

function overops_fix_permissions()
{
	chmod 777 $overops_home/log/agents
	chmod 777 $overops_home/resources
}

function overops_write_creds_file()
{
	if [ "$overops_secret_key" != "" ]; then
		echo $overops_secret_key > $overops_installation_key_file
		chmod 600 $overops_installation_key_file

		overops_update_service_id
	fi
	
	if [ "$overops_installation_token" != "" ]; then
		echo $overops_installation_token > $overops_installation_token_file
		chmod 600 $overops_installation_token_file
	fi
}

function overops_update_service_id()
{
	local new_service_id=$overops_service_id
	
	overops_load_config_file "1"
	overops_service_id=$new_service_id
	overops_save_config_file
}

function overops_prepare_init_file()
{
	local target_init_file=$1
	local template_files_dir=$2
	local pid_file_path=$3
	local ulimit_token="@ULIMIT_TOKEN@"
	local init_file_name=""
	local ulimit_statement=""

	if [ "$os_init_system_type" == "upstart" ]; then
		if [ "$os_distribution_name" == "Ubuntu" ]; then
			init_file_name="$template_files_dir/takipi.init-upstart"
		elif [ "$os_distribution_name" == "Redhat" ]; then
			init_file_name="$template_files_dir/takipi.init-upstart-rhel"
		else
			log $error "Error configure upstart for $os_distribution_name"
			return 1
		fi
		
		if [ -n "$overops_max_file_descriptors" ]; then
			ulimit_statement="limit nofile $overops_max_file_descriptors $overops_max_file_descriptors"
		fi
	elif [ "$os_init_system_type" == "systemd" ]; then
		init_file_name="$template_files_dir/takipi.init-systemd"
		
		if [ -n "$overops_max_file_descriptors" ]; then
			ulimit_statement="LimitNOFILE=$overops_max_file_descriptors"
		fi
	else # sysvinit/openrc
		if [ "$os_distribution_name" == "Ubuntu" ]; then
			init_file_name="$template_files_dir/takipi.init-debian"
		elif [ "$os_distribution_name" == "Redhat" ]; then
			init_file_name="$template_files_dir/takipi.init-rhel"
		elif [ "$os_distribution_name" == "Gentoo" -o "$os_distribution_name" == "Alpine" ]; then
			init_file_name="$template_files_dir/takipi.init-gentoo"
		elif [ "$os_distribution_name" = "SuSE" ]; then
			init_file_name="$template_files_dir/takipi.init-suse"
		else
			log $error "Error configure sysvinit for $os_distribution_name"
			return 1
		fi
	
		if [ -n "$overops_max_file_descriptors" ]; then
			ulimit_statement="ulimit -n $overops_max_file_descriptors"
		fi
	fi
	
	log $verbose "Preparing init file $init_file_name (ulimit: $ulimit_statement)"
	
	cp -f "$init_file_name" "$target_init_file"
	sed -i "s|$ulimit_token|$ulimit_statement|g" $target_init_file
	sed -i "s|PIDFILE=.*|PIDFILE=$pid_file_path|g" $target_init_file
	sed -i "s|@USER@|$overops_user_name|g" $target_init_file
	sed -i "s|@GROUP@|$overops_user_group|g" $target_init_file
	sed -i "s|@HOME@|$overops_home|g" $target_init_file

	return 0
}

function overops_install_daemon()
{
	local init_file_name="$overops_home/etc/temp.init.file"
	local pid_file_path="$overops_home/var/run/takipi.pid"
	
	if ! overops_prepare_init_file "$init_file_name" "$overops_home/etc" "$pid_file_path"; then
		return 1
	fi
	
	if ! daemon_install "$overops_name" "$init_file_name"; then
		return 1
	fi
	
	return 0
}

function overops_upload_logs_dir()
{
	java_run -cp $overops_bootstrap_jar m.M remotelogs "$overops_secret_key" "$overops_home" "$overops_backend_url" "uninstall"
}

function overops_validate_installation_with_different_secret_key()
{
	if [ -n "$overops_secret_key" -a -r "$overops_installation_key_file" ]; then
		local existing_secret_key=`cat $overops_installation_key_file` >/dev/null 2>&1
		
		if [ -n "$existing_secret_key" ]; then
			if [ "$existing_secret_key" != "$overops_secret_key" ]; then
				log $error "An existing installation with a different key was found, Please uninstall first and then try again."
				return 1
			fi
		fi
	fi
	
	return 0
}

function overops_prepare_takipi_home()
{
	local installer_tarball_url=$1
	
	local tarball_local_path=""
	local should_remove_tarball=""
	
	if [ -r "$installer_tarball_url" ]; then
		tarball_local_path="$installer_tarball_url"
		should_remove_tarball="0"
	else
		log $info "Getting the latest $overops_product_name version..."
		
		local unique_temp_file=$overops_tmp_dir/$(mktemp package-latest-XXXXXX)
		local temp_tarball="${unique_temp_file}.tar.gz"
		rm -f $unique_temp_file >/dev/null 2>&1
		
		if ! network_download $installer_tarball_url $temp_tarball; then
			log $error ""
			log $error "Aborting. Unable to download: $installer_tarball_url"
			log $error ""
			log $error "$overops_product_name's installer was not able to communicate with the server."
			log $error ""
			log $error "Are you running behind a proxy/firewall? Learn how to set up your proxy:"
			log $error "  https://support.$overops_name.com/hc/en-us/articles/218721168#running-behind-a-proxy"
			log $error ""
			
			rm -f $temp_tarball >/dev/null 2>&1
			
			report_status 1
			return 1
		fi
		
		tarball_local_path=$temp_tarball
		
		log $info "File downloaded successfully."
		should_remove_tarball="1"
	fi

	local overops_base=`dirname $overops_home`
		
	log $verbose "Extracting $tarball_local_path to $overops_base"
	tar -C $overops_base -xf $tarball_local_path >/dev/null 2>&1
	
	if [ "$?" != "0" ]; then
		return $?
	fi

	if [ "$should_remove_tarball" == "1" ]; then
		rm -f $tarball_local_path >/dev/null 2>&1
	fi
	
	return 0
}

function overops_setup_unprivileged()
{
	if [ "$overops_priviliged_mode" == "1" ]; then
		return 0
	fi
	
	if ! os_create_user "$overops_user_name" "$overops_user_password" "$overops_home"; then
		log $error "Failed to add user $overops_user_name..."
		return 1
	fi
	
	log $verbose "Trying to set user:group $overops_user_name:$overops_user_group for $overops_home"

	if [ -n "$overops_user_name" -a -n "$overops_user_group" ]; then
		local local_user=$(stat -c '%U' $overops_home)
		local local_group=$(stat -c '%G' $overops_home)

		log $verbose "$overops_home is currently owned by $local_user:$local_group"
		
		if [ "$overops_user_name" != "$local_user" -o "$overops_user_group" != "$local_group" ]; then
			log $info "Changing ownership of $overops_home - $overops_user_name:$overops_user_group may take time if directory is big"
			
			if ! chown -R $overops_user_name:$overops_user_group $overops_home; then
					log $warn "  Unable to change ownership of $overops_home"
			fi
			
			# TTT: in case user change work/log dir location
			for filename in "$overops_home"/*; do
				if [ -L "$filename" ]; then
					log $verbose "  Changing ownership of symlink: $filename"
					
					if ! chown -h $overops_user_name:$overops_user_group $filename; then
						log $warn "  Unable to change ownership of $filename"
					fi
					
					if ! chown -R $overops_user_name:$overops_user_group $filename/; then
						log $warn "  Unable to change ownership of $filename subfolders"
					fi
				fi
			done
		else
			# The overops home folder is owned by the overops user. Make sure the first and second levels are also owned by it
			for filename in "$overops_home"/*; do
				if [ -L "$filename" ]; then
					log $verbose "  Changing ownership of symlink: $filename"
					
					if ! chown -h $overops_user_name:$overops_user_group $filename; then
						log $warn "  Unable to change ownership of $filename"
					fi

					if ! chown -R $overops_user_name:$overops_user_group $filename/; then
						log $warn "  Unable to change ownership of $filename subfolders"
					fi
				elif [ -d "$filename" ]; then
					log $verbose "  Changing ownership of folder: $filename"

					if ! chown $overops_user_name:$overops_user_group $filename; then
						log $warn "  Unable to change ownership of $filename"
					fi

					for subfilename in "$filename"/*; do
						if ! chown $overops_user_name:$overops_user_group $subfilename; then
							log $warn "  Unable to change ownership of $subfilename"
						fi
					done
				else
					log $verbose "  Changing ownership of file: $filename"

					if ! chown $overops_user_name:$overops_user_group $filename; then
						log $warn "  Unable to change ownership of $filename"
					fi
				fi
			done
		fi
	fi 
	
	# CCC: I don't trust this code, that is why i do things a bit differently above
	if ! os_fix_home_folder_ownership "$overops_user_name"; then
		log $error "Failed to fix takipi home folder ownership"
		return 1
	fi

	return 0
}

function overops_run_wipe_data()
{	
	if ! utils_delete_directory "$overops_home/work" "$overops_home/wipe-tmp"; then
		log $error "Failed to delete $overops_home/work"
		return 1
	fi
	
	if ! utils_delete_directory "$overops_home/log/agents" "$overops_home/wipe-tmp"; then
		log $error "Failed to delete $overops_home/log/agents"
		return 1
	fi
	
	if ! utils_safe_move_file "$overops_home/log/bugtale_service.log" "$overops_home/bugtale_service.log.old"; then
		return 1
	fi
	
	log $info "Successfully wiped collector's data!"
	
	return 0
}

# java.sh is part of our bash shared utils, it can't report status by itself.
#	However, it should check if a function named java_report_status_hook is exists
#	and if it founds it it call it with the status it wants to report
#
function java_report_status_hook()
{
	report_status $1
}

function overops_get_service_process()
{
	ps -ef | grep "$overops_home/bin/takipi-service" | grep -v grep | awk '{print $2}'
}

overops_init $utils_script_params

# source agent-attachment.sh
# source logs.sh
# source reports-codes.sh
# source overops.sh

declare -ra param_install=("install" "i" "" "Do install")
declare -ra param_tarball_url=("installer_url" "" "" "Specify installation tarball URL")
declare -ra param_wipe=("wipe" "" "" "Wipe Collector's data")

declare installer_tarball_url=""

function installation_usage()
{
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_tarball_url[0]}" "${param_tarball_url[3]}" "${param_tarball_url[2]}"
	printf "%-5s %-20s %-70s %s$end_line" "" "--${param_wipe[0]}" "${param_wipe[3]}"
}

function installation_parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi

	 	case $1 in
			--${param_install[0]}|-${param_install[0]}|-${param_install[1]}|--${param_install[1]})
				shift 1
			;;
			--${param_tarball_url[0]}|-${param_tarball_url[0]}|--${param_tarball_url[1]}|-${param_tarball_url[1]})
				shift 1
				installer_tarball_url=$1
				log $verbose "Param: ${param_tarball_url[0]} = $installer_tarball_url"
				shift 1
			;;
			--${param_tarball_url[0]}=*|-${param_tarball_url[0]}=*|--${param_tarball_url[1]}=*|-${param_tarball_url[1]}=*)
				installer_tarball_url=${1#*=}
				log $verbose "Param: ${param_tarball_url[0]} = $installer_tarball_url"
				shift 1
			;;
			--${param_wipe[0]}|-${param_wipe[0]}|--${param_wipe[2]}|-${param_wipe[2]})
				overops_wipe="true"
				log $verbose "Param: ${param_wipe[0]} = true"
				shift 1
			;;
			*)
				shift 1
			;;
		esac
	done
}

function installation_init()
{
	installation_parse_command_line $@
}

function show_final_installation_message()
{
	local link_color='\e[49;96m'
	local clear_color='\E[00m'

	echo " "
	local space="                          "
	echo 	"***************************************************************************************"
	echo -e "* Head over to ${link_color}$overops_frontend_url${clear_color} to start using $overops_product_name.$space*" 
	echo 	"***************************************************************************************"
	echo " "
}

function show_setup_package_message()
{
	local highlight_color='\e[1;38;5;208;48;5;232m'
	local clear_color='\E[00m'

	echo ""
	echo "Next step - run the following command:"
	echo ""
	echo -e "${highlight_color}sudo $overops_home/etc/${overops_name}-setup-package <installation-key>${clear_color}."
	echo ""
	echo "(For further instructions, go to: $overops_frontend_url)"
	echo ""
}

function validate_install()
{
	local validate_secret_key=$1

	if ! overops_can_run_installation; then
		return 1
	fi

	if [ "$validate_secret_key" == "1" ] ; then
		if [ -z "$overops_secret_key" -a -z "$overops_installation_token" ]; then
			log $error "Please provide an installation key or token."

			report_status 10
			return 1
		fi

		if ! overops_validate_installation_with_different_secret_key; then
			return 1
		fi

		if [ "$overops_is_valid_creds" == "0" ]; then
			log $error "The installation key/token is invalid. Please provide a valid installation key/token."
			log $error ""

			report_status 8
			return 1
		fi
	fi

	if [ "$overops_is_aos_mode" == "1" ]; then
		log $info "Agent configured for remote collector $overops_daemon_host:$overops_daemon_port"
	fi
}

function get_proxy_from_user()
{
	local server_url=$1
	local server_display_name=$2

	if [ "$utils_non_interactive_mode" == "1" ]; then
		return 0
	fi

	log $warn "Could not establish a connection to $server_display_name's server."
	log $info "If you are behind a proxy, please enter its details (e.g. \"http://user:pass@192.168.1.101:8080\")."

	local proxy_from_user=""

	while true; do
		read -e -p "Proxy address (leave empty to skip): " proxy_from_user < /dev/tty
		
		if [ -z "$proxy_from_user" ]; then
			return 1
		fi
		
		network_set_proxy "$proxy_from_user"
		
		if java_check_connection "$server_url" "$overops_bootstrap_jar"; then
			return 0
		fi
		
		log $warn "We still couldn't reach $server_display_name's servers. Please enter a valid proxy address."
	done
}

function prepare_takipi_home_from_tarball()
{
	if [ -z "$installer_tarball_url" ]; then
		installer_tarball_url=$1
	fi

	if [ -z "$installer_tarball_url" ]; then
		log $error "Error: $overops_product_name download URL is empty."
		log $error "Aborting installation."
		return 1
	fi

	if [ -n "$overops_service_id" ]; then
		if [ ! -r "$installer_tarball_url" ]; then
			if [[ $installer_tarball_url == *"?"* ]]; then
				installer_tarball_url="${installer_tarball_url}&"
			else
				installer_tarball_url="${installer_tarball_url}?"
			fi
			
			installer_tarball_url="${installer_tarball_url}s=${overops_service_id}"
		fi
	fi

	if ! overops_prepare_takipi_home "$installer_tarball_url"; then
		return 1
	fi
}

function collector_network_test()
{
	if [ "$overops_is_aos_mode" == "0" ]; then
		if ! java_found_valid_java; then
			java_show_invalid_java_message "$overops_product_name"
			return 1
		fi

		if ! java_check_connection "$overops_backend_url" "$overops_bootstrap_jar"; then
			get_proxy_from_user "$overops_backend_url" "$overops_product_name"
		fi

		if ! java_check_connection "$overops_s3_ping_url" "$overops_bootstrap_jar"; then
			get_proxy_from_user "$overops_s3_ping_url" "$overops_product_name Storage"
		fi
	fi
}

function configure_overops()
{
	report_status 21
	report_status 60 "$os_machine_architecture"

	if [ "$java_should_install_jdk" == "1" ]; then
		java_install_provided_jdk
	fi

	if [ "$overops_installed" == "1" ]; then
		report_status 40 "$os_distribution_name, $os_system_information"
	else
		report_status 41 "$os_distribution_name, $os_system_information"
	fi

	if [ "$overops_is_aos_mode" == "0" ]; then
		daemon_stop "$overops_name" "$overops_exe_name"

		overops_export_daemon_envs
		overops_save_default_file
	fi
	
	overops_save_config_file
	
	if ! overops_prepare_directories; then
		return 1
	fi
	
	overops_fix_permissions
	dynamic_libs_add_location "$overops_name" "$overops_lib_directory"

	if [ "$overops_is_aos_mode" == "0" ]; then
		if ! overops_install_daemon; then
			return 1
		fi

		log $verbose "Registering..."

		overops_write_creds_file
		
	fi

	if ! overops_setup_unprivileged ; then
		log $error "Failed to install takipi under non-priviliged user"
		return 1
	fi

	log $info "$overops_product_name installed successfully."
	log $info "This machine's name is \"$overops_machine_name\". You can change it by running: $overops_home/etc/$overops_name-setup-machine-name <machine-name>."

	if [ "$agent_smart_attach_enabled" == "1" ]; then
		agent_enable_smart_attach "$overops_service_id" "$overops_backend_url" "$overops_bootstrap_jar"
	fi

	if [ "$agent_auto_agent_enabled" == "0" ]; then
		agent_show_attachment_instructions "$overops_lib_name" "$overops_product_name" "$overops_site_url"
	else
		agent_enable_auto_agent "$overops_agent_file" "$overops_home/lib32/lib$overops_lib_name.so" "$overops_home/etc/$overops_name-env-install"
	fi

	if [ "$overops_wipe" == "true" ]; then
		log $verbose "Start collecotr cleanup"
		if ! overops_run_wipe_data; then 
			log $error "Error wipe collecotr's data"
			return 1
		fi
	fi

	if [ "$overops_t4c_mode" != "true" -a "$overops_is_aos_mode" == "0" ]; then
		if [ "$overops_is_valid_creds" == "1" ]; then
			if ! daemon_start "$overops_name"; then
				report_status 9 "$?"
				log $error "Error starting daemon ($os_init_system_type)"
				return 1
			fi

			report_status 62
		fi
	fi

	if [ "$agent_auto_agent_enabled" == "1" ]; then
		agent_show_attach_message "$overops_product_name" "$overops_home" "$overops_lib_name" "$overops_exe_name" "$overops_name"
	fi

	if [ "$overops_is_valid_creds" == "1" -o "$overops_is_aos_mode" == "1" ]; then
		show_final_installation_message
	else
		show_setup_package_message
	fi

	report_status 22
}

installation_init $utils_script_params

declare -ra param_help=("help" "h" "" "Print this usage")

declare -r nix_installer_tarball_url="$overops_frontend_url/app/download?t=tgz&r=nix-installer"

function usage()
{
	if [ "$utils_non_interactive_mode" == "1" ]; then
		return
	fi

	local script_name=`basename "$0"`
	local end_line="\n  "
	
	printf "\n"
	printf "Usage: ./$script_name [options]$end_line"
	printf "$end_line"
	printf "%-5s %-20s %-70s %s$end_line" "-${param_help[1]}" "--${param_help[0]}" "${param_help[3]}" "${param_help[2]}"

	installation_usage
	log_usage
	utils_usage
	java_usage
	agent_usage
	overops_usage
	network_usage

	printf "\n"
}

function parse_command_line()
{
	while true; do
		if [ -z $1 ]; then
			break
		fi

	 	case $1 in
	 		--${param_help[0]}|-${param_help[0]}|-${param_help[1]}|--${param_help[1]}|-\?)
				usage
				exit 0
			;;
			*)
				shift 1
			;;
		esac
	done
}

function run_osx_oneliner()
{
	# This is a fallback for OSX users which accidentally run the Linux oneliner
	#

	log $verbose "Downloading $overops_product_name..."

	local temp_pkg_name=`mktemp $overops_tmp_dir/osx-pkg-XXXXXX`
	local temp_pkg_file="${temp_pkg_name}.pkg"

	local osx_package_url="$overops_frontend_url/app/download?t=pkg&r=nix-installer"

	if ! network_download "$osx_package_url" "$temp_pkg_file" "1"; then
		return 1
	fi

	# These files are expected to be found by the OSX installer
	#	Have a look at ops/scripts/osx/scripts/osx-pkg-installer.sh
	#
	echo $overops_secret_key > $overops_tmp_dir/takipi-skf
	echo $temp_pkg_file > $overops_tmp_dir/takipi-dtp

	report_status 61

	open "$temp_pkg_file"
}

function main()
{
	parse_command_line $@

	report_status 11
	report_status 71 "$os_init_system_type"

	if [ "$os_distribution_name" == "OSX" ]; then
		run_osx_oneliner
		return 0
	fi

	if ! validate_install "1" ; then
		log $error "Failed to prepare the installation"
		return 1
	fi

	if [ "$overops_dry_run" == "1" ]; then
		log $info "Finished base validation successfully, exiting on dry run..."
		return 0
	fi

	if ! prepare_takipi_home_from_tarball "$nix_installer_tarball_url" ; then
		return 1
	fi

	if ! collector_network_test; then
		log $error "Network test failed" 
		return 1
	fi

	if ! configure_overops; then
		log $error "Failed to configure OverOps"
		return 1
	fi

	report_status 12
}

main $utils_script_params