#!/usr/bin/env bash
set -e
shopt -s nullglob

# utilities 
now_time(){
    echo "`date +"%F"T"%T.%3N"Z`"
}
now_short_time(){
    echo "`date +"%Y%m%d%H%M"`"
}
show_message(){
	if [ -n "$1" ]
	then
    	IN="$1"
	else
    	read IN
  	fi
    echo "$IN" >&3
    log "$IN"
}
show_error(){
    echo "ERROR: $1" >&4
    log "$1"
}
log(){
    if [ -n "$1" ]
    then
        IN="$1"
    else
        read IN
    fi
    echo $(now_time)": $IN"
}
set_working_dir(){
    working_dir=$(echo "$working_dir"|sed 's/[\/]*$//g')"/"
    log_location=$working_dir"logs/"
    tmp_location=$working_dir"tmp/"
    chunk_location=$working_dir"data/"
    export CLOC=$chunk_location
}
setup_logs(){
    # backing up logs from previous runs
    if [[ "$(file_valid $log_location'/log.out' )" = true ]] ; then
        echo $log_location"/log.out" > $log_location"/log_previous_"$unique_run_id".out"
    else
        mkdir -p $log_location
        echo "">$log_location"/log.out"
		local retVal2=$?
        if [[ "$retVal1" -ne 0 ]]; then
            show_error "Could write to log. Will not proceed with data migration operation."
            exit 2;
        fi
    fi 
}
set_redirects() {
    setup_logs
    exec 3>&1 4>&2
    trap 'exec 2>&4 1>&3' 0 1 2 3
    exec 1>$log_location"/"log.out 2>&1
}
show_help(){
    show_message "A utility to import influx csv export to es. ©JFrog 2017"
    show_message "Usage requires below parameters"
    show_message "--username username in elasticsearch"
    show_message "--password password in elasticsearch"
    show_message "--esurl Base url of elastic search like http://localhost:9200/ "
    show_message "--csvpath Path to where the csv files reside"
    show_message "---workingdir Path to the folder under which logs will be written"
}
parse_parameters(){
    while :; do
        case $1 in
            -h|-\?|--help)
                show_help    # Display a usage synopsis.
                exit
                ;;
            -y|--yes)
				skip_prompts=true
                ;;    
            -username|--username)
                if [ "$2" ]; then
                    userName=$2
                    shift
                else
                    show_error 'ERROR: "--username" requires a non-empty option argument.'
                fi
                ;;
            -password|--password)
                if [ "$2" ]; then
                    password=$2
                    shift
                else
                    show_error 'ERROR: "--password" requires a non-empty option argument.'
                fi
                ;;   
			-esurl|--esurl)
                if [ "$2" ]; then
                    es_base_url=$2
                    shift
                else
                    show_error 'ERROR: "--esurl" requires a non-empty option argument.'
                fi
                ;; 
            -csvpath|--csvpath)
                if [ "$2" ]; then
                    conv_csv_location=$2
                    shift
                else
                    show_error 'ERROR: "--csvpath" requires a non-empty option argument.'
                fi
                ;;
			-workingdir|--workingdir)
                if [ "$2" ]; then
                    working_dir=$2
                    shift
                else
                    working_dir="$(dirname "$0")"
                    show_error 'ERROR: "--workingdir" was found empty. Will write logs to the same folder as migrate.'
                fi
                ;;
            --)  # End of all options.
                shift
                break
                ;;
            -?*)
                show_error "Unknown option: $1. Will not proceed with data migration operation."
                exit; 
                ;;
            *) # Default case: No more options, so break out of the loop.
                break
        esac
        shift
    done
}
check_chunk_folder() {
    chunk_files=(${chunk_location}*/*.json)
    chunk_files_count=${#chunk_files[@]}
    log "Found $chunk_files_count (nd)json files"
    if [ $chunk_files_count -ne 0 ]
    then
        log "Found some data files. Setting status_chunk_files_present as true"
        status_chunk_files_present=true
    else
        status_chunk_files_present=false    
    fi
}

check_csv_folder() {
    csv_files=($conv_csv_location/*.csv)
    csv_files_count=${#csv_files[@]}
    log "Found $csv_files_count csv files"
    if [ $csv_files_count -ne 0 ]
    then
        log "Setting status_csv_files_present as true"
        status_csv_files_present=true
    else
        log "No csv files found. Setting status_csv_files_present as false"
        status_csv_files_present=false
    fi
}


folder_valid() {
    if [ -d "$1" -a -w "$1" ]
    then
        echo true
    else
        echo false
    fi
}
file_valid(){
    if [ -f "$1" -a -s "$1" -a -w "$1" ]; 
	then 
	   echo true
	else
	   echo false
	fi
}
file_executable(){
    if [ -f "$1" -a -x "$1" ];
    then
       echo true
    else
       echo false
    fi
}
check_validity() {
	log "Checking validity"
	local check=true

    #working directory 
    printf "Provide a working directory for writing the logs folder <$working_dir>:" >&3
    read -r working_dir1
    if [ ! -z "$working_dir1" ];then
        working_dir=$working_dir1
    fi
    if [ -z "$working_dir" ];then
        show_error "Couldnt find working directory to write logs. Cannot proceed."
        check=false
    fi
	
	#elastic search url 
	printf "Provide the baseurl for elasticsearch <$es_base_url>:" >&3
	read -r es_base_url1
	if [ ! -z "$es_base_url1" ];then
		es_base_url=$es_base_url1
	fi
	if [ -z "$es_base_url" ];then
		show_error "Couldnt find elastic search base url. Cannot proceed."
		check=false
	fi

	#username 
	printf "Provide the username for authentication with elasticsearch:" >&3
	read -r userName
	if [ -z "$userName" ];then
		show_error "Couldnt find username to elastic search. Assuming no authentication."
	fi

	#password 
	if [[ ! -z "$userName" ]]  && [[ -z "$password"  ]];then
		printf "Provide the password for authentication with elasticsearch :" >&3
		read -r password
		if [ -z "$password" ];then
			show_error "Couldnt find password to elastic search. Cannot proceed."
			check=false
		fi
	fi

	#csvpath 
	printf "Provide the full path to csv location for conversion <$conv_csv_location>:" >&3
	read -r conv_csv_location1
	if [ ! -z "$conv_csv_location1" ];then
		conv_csv_location=$conv_csv_location1
	fi
	if [ -z "$conv_csv_location" ];then
		show_error "Couldnt find csv location. Cannot proceed."
		check=false
	fi

    conv_csv_location=$(echo "$conv_csv_location"|sed 's/[\/]*$//g')"/"
    es_base_url=$(echo "$es_base_url"|sed 's/[\/]*$//g')"/"

	if [[ "$(file_valid $convertor_location)" = false  ]] ; then
		check=false
		show_error "Cannot read the convertor.awk file in folder. Possible corrupt file"
    fi

    show_message "CSV path used is "$conv_csv_location
    show_message "Username used is "$userName
    show_message "Elastic search baseurl used is "$es_base_url

    if [[ "$check" = true ]] ; then
   		status_validity_check=true
		log "Validity check successfully completed!"
	else
		show_error "Found errors when initilaizing. Will not proceed with data migration operation."
        exit 1;
    fi   
}
check_state(){
    log "Checking states"
    status_tmp_present=$(folder_valid $tmp_location)        	
    check_chunk_folder
    check_csv_folder
    #check pipe state
    check_previous

    # Asking for a user confirmation 
	if [[ "$skip_prompts" = false ]] ; then
		printf "Do you want to migrate usage metrics data to elasticsearch? (check upgrade notes for more info)  (y/n) :" >&3
		read -r user_prompt
		if [[  "$user_prompt" = "y" ]]  || [[ "$user_prompt" = "yes" ]] ; then
			show_message "Proceeding with data migration operation."
		else
			show_error "Will not proceed with data migration operation."
			exit 1;
		fi
	fi
}
check_previous(){
	status_file_path=${tmp_location}"/"${status_file}
   	if [[ "$(file_valid $status_file_path )" = true ]] ; then
    show_message "Found earlier attempts to run migration. If data insert status or alias status was successful, please delete the index manually, clear tmp folder and try again."
		show_message "                         Datestamp   -   Data insert status   -   Aliasing status" 
		while read -r run_id partial_data alias_failed; do
            msg=""
            if [[ "$partial_data" = false ]] ; then
                msg=$msg"   complete"
            else
                msg=$msg"   failed "
            fi
			if [[ "$alias_failed" = false ]] ; then
                msg=$msg"                 success"
            else
                msg=$msg"                 failed "
            fi    
			show_message "Previous run detected at $run_id $msg"
		done < ${tmp_location}"/"${status_file}
	fi 
}
house_keeping() {
    log "Starting housekeeping"
	
	if [[ "$status_tmp_present" = false ]] ; then
        show_message "Creating tmp folder"
		mkdir -p $tmp_location;
		local retVal=$?
		if [ $retVal -ne 0 ]; then
			show_error "Could not create $tmp_location which is required for execution. Will not proceed with data migration operation."
			exit 2;
		fi
    fi	

	if [[  "$status_csv_files_present" = false ]]  && [[ "$convert_csv" = true ]] ; then
    	show_error "Could not find csv files to convert. Will not proceed with data migration operation."
		exit 1;
    fi

	if [[  "$status_chunk_files_present" = true ]] ; then
        show_message "Some data files are already present at $chunk_location/"
		chunk_location=$chunk_location"/"${unique_run_id}/
		show_message "Will create data chunks to $chunk_location/"
		mkdir -p $chunk_location"/"$es_repo_type_name;
        local retVal1=$?
		mkdir -p $chunk_location"/"$es_instance_type_name;
        local retVal2=$?
        if [[ "$retVal1" -ne 0 ]] ||  [[ "$retVal2" -ne 0 ]]; then
            show_error "Could not create data folders which is required for execution. Will not proceed with data migration operation."
            exit 2;
        fi
	else
		chunk_location=$chunk_location"/"${unique_run_id}/
		mkdir -p $chunk_location"/"$es_repo_type_name;
        local retVal1=$?
        mkdir -p $chunk_location"/"$es_instance_type_name;
        local retVal2=$?
        if [[ "$retVal1" -ne 0 ]] ||  [[ "$retVal2" -ne 0 ]]; then
            show_error "Could not create data folders which is required for execution. Will not proceed with data migration operation."
            exit 2;
        fi
    fi
    status_house_keeping=true
}
export_vars() {
    export CLPF=$conv_lines_per_file
    export CLOC=$chunk_location
}
init(){
    unique_run_id="$(now_short_time)"
    skip_prompts=false
    partial_migration=false
    alias_failed=false
	parse_parameters "$@"
    set_working_dir
	set_redirects
	check_validity
	check_state
	house_keeping
    export_vars
}

init "$@"

