#!/bin/bash

# Initialize variables
ENV_VARS=""
PORT=10061
START_TIME=""
DISALLOW_MULTIPLE_STARTS=""
OUTPUT_PATH=""
FUNCTION_NAMES=""

# Function to display usage
show_usage() {
    echo "Usage: $0 -z <server> -U <user> -P <password> -j <job_name> [-E <environment-variable>] [-p <port> -t <YYYYMMDDHHMM> -D] [-e <function-name>] [-o <absolute_output_path>]"
    echo "Options:"
    echo "  -z <server>              		Specify the IP address or host name of the Job Server."
    echo "  -U <user>                		Specify the user name to log in to the Job Server."
    echo "  -P <password>           		Specify the user's password."
    echo "  -j <job_name>            		Specify the job net ID to be started."
    echo "  -E <environment-variable> 		Specify an environment variable for the external I/F execution environment to the job net."
    echo "                           		Specify only the environment variable name (e.g. LANG)."
    echo "                           		For multiple environment variables, separate them with a comma."
    echo "  -p <port>               	 	Optional: Specify the port number of the Job Server. Default is 10061."
    echo "  -t <YYYYMMDDHHMM>        		Optional: Start the job net on a specified date and time."
    echo "  -D                       		Optional: When '-t' is specified, prohibit multiple starts with the same start time and job net ID."
    echo "  -e <function-environment-variable> 	Specify an environment variable for calling function and get return value."
    echo "                           		Specify only the environment variable name (e.g. GETHOSTIP)."
    echo "                           		For multiple environment variables, separate them with a comma."
    echo "  -o <absolute_output_path> Optional: Specify the output file path including filename. Default is /tmp/."
}

# Parse arguments using getopts
while getopts "z:U:P:j:E:p:t:De:o:" opt; do
    case $opt in
        z) SERVER=$OPTARG ;;
        U) USER=$OPTARG ;;
        P) PASSWORD=$OPTARG ;;
        j) JOB_NAME=$OPTARG ;;
        E) ENV_VARS=$OPTARG ;;
        p) PORT=$OPTARG ;;
        t) START_TIME=$OPTARG ;;
        D) DISALLOW_MULTIPLE_STARTS="-D" ;;
        e) FUNCTION_NAMES=$OPTARG ;;
        o) OUTPUT_PATH=$OPTARG ;;
        *) show_usage; exit 4 ;;
    esac
done

# Check if the required arguments are provided
if [ -z "$SERVER" ] || [ -z "$USER" ] || [ -z "$PASSWORD" ] || [ -z "$JOB_NAME" ]; then
    show_usage
    exit 4
fi

# Create a temporary file to capture the output of jobarg_exec
TEMP_FILE=$(mktemp)

# Prepare the jobarg_exec command
JOBARG_EXEC_CMD="jobarg_exec -z $SERVER -U $USER -P $PASSWORD -j $JOB_NAME"
[ -n "$ENV_VARS" ] && JOBARG_EXEC_CMD+=" -E $ENV_VARS"
[ -n "$PORT" ] && JOBARG_EXEC_CMD+=" -p $PORT"
[ -n "$START_TIME" ] && JOBARG_EXEC_CMD+=" -t $START_TIME"
[ -n "$DISALLOW_MULTIPLE_STARTS" ] && JOBARG_EXEC_CMD+=" $DISALLOW_MULTIPLE_STARTS"
[ -n "$FUNCTION_NAMES" ] && JOBARG_EXEC_CMD+=" -e $FUNCTION_NAMES"

# Run the jobarg_exec command and capture the registry number
$JOBARG_EXEC_CMD > "$TEMP_FILE" 2>&1

# Check if the temporary file is empty
if [ ! -s "$TEMP_FILE" ]; then
    echo "Failed to get output from jobarg_exec."
    rm "$TEMP_FILE"
    exit 1
fi

# Print the contents of the temporary file for debugging
cat "$TEMP_FILE"

# Extract the registry number using grep
REGISTRY_NUMBER=$(grep -oP '(?<=Registry number :  \[)[0-9]+(?=\])' "$TEMP_FILE")

# Ensure the registry number is not empty
if [ -z "$REGISTRY_NUMBER" ]; then
    echo "Failed to capture registry number."
    rm "$TEMP_FILE"
    exit 1
fi

# Clean up the temporary file
rm "$TEMP_FILE"

# Initialize status
STATUS="RUN"
JOB_STATUS="RUN"

symbols=('|' '/' '-' '\\')
message="Jobnet is running..."
sleep_duration=0.25

while [ "$STATUS" != "END" ]; do
    # Display rotating symbols
    for symbol in "${symbols[@]}"; do
        echo -ne "${message} ${symbol}\r"
        sleep $sleep_duration
    done

    # Get the job status using jobarg_get with -e option
    STATUS_TEMP_FILE=$(mktemp)
    jobarg_get -z "$SERVER" -U "$USER" -P "$PASSWORD" -r "$REGISTRY_NUMBER" -e | awk '/^export JA_LASTEXITCD/ {exit} {print}' > "$STATUS_TEMP_FILE" 2>&1
    echo -ne "\r"

    # Check if the temporary file is empty
    if [ ! -s "$STATUS_TEMP_FILE" ]; then
        echo "ERROR: Failed to get output from jobarg_get."
        rm "$STATUS_TEMP_FILE"
        sleep 2
        continue
    fi

    # Source the file to load environment variables
    source "$STATUS_TEMP_FILE"

    # Extract the statuses from the environment variables
    STATUS=$JA_JOBNETSTATUS
    JOB_STATUS=$JA_JOBSTATUS

    rm "$STATUS_TEMP_FILE"

    if [ "$STATUS" == "RUN" ] && [ "$JOB_STATUS" == "ERROR" ]; then
        echo "Jobnet status is RUN and job status is ERROR."
        break
    elif [ "$STATUS" == "ENDERR" ] && [ "$JOB_STATUS" == "ERROR" ]; then
        echo "Jobnet status is ENDERR and job status is ERROR."
        break
    elif [ "$STATUS" == "END" ]; then
        echo "Jobnet is successfully DONE."
        break
    fi

    sleep 2
done

# Capture the final status output
STATUS_TEMP_FILE=$(mktemp)
stdout_file=$(mktemp)
stderr_file=$(mktemp)
jobarg_get -z "$SERVER" -U "$USER" -P "$PASSWORD" -r "$REGISTRY_NUMBER" > "$STATUS_TEMP_FILE" 2>&1

# Extract the 'Last job return value'
EXIT_CODE=$(awk -F': ' '/Last job return value/ {print $2}' "$STATUS_TEMP_FILE" | tr -d '[:space:]')

# Extract 'Last job standard output'
start_stdout=$(awk '/Last job return value/ {print NR}' "$STATUS_TEMP_FILE")
end_stdout=$(awk '/Last job standard error  :/ {print NR}' "$STATUS_TEMP_FILE")
if [ -n "$start_stdout" ] && [ -n "$end_stdout" ]; then
    sed -n "$((start_stdout + 1)),$((end_stdout - 1))p" "$STATUS_TEMP_FILE" | sed 's/^[[:space:]]*//' > "$stdout_file"
fi

# Extract 'Last job standard error'
headErr=$(awk '/Last job standard error  :/ {print}' "$STATUS_TEMP_FILE")
cleanedHeadErr=$(echo "$headErr" | sed 's/^Last job standard error  : *//')
start_stderr=$(awk '/Last job standard error  :/ {print NR}' "$STATUS_TEMP_FILE")
if [ -n "$start_stderr" ]; then
    sed -n "$((start_stderr + 1)),\$p" "$STATUS_TEMP_FILE" | sed 's/^[[:space:]]*//' > "$stderr_file"
fi

# Output the results
# Check if the stdout file exists
if [ -f "$stdout_file" ]; then
    # Read the content of the stdout file
    STDOUT=$(cat "$stdout_file")	
    STDOUT=$(echo "$STDOUT" | sed 's/^Last job standard output ://')
    # Trim only leading whitespace
    STDOUT=$(echo "$STDOUT" | sed 's/^[[:space:]]*//')
else
    echo "Error: $stdout_file does not exist."
    STDOUT=""
fi

# Check if the stderr file exists
if [ -f "$stderr_file" ]; then
    # Read the content of the stderr file
    STDERR=$(printf "%s\n%s" "$cleanedHeadErr" "$(cat "$stderr_file")")
else
    echo "Error: $stderr_file does not exist."
    STDERR=""
fi

rm "$stdout_file"
rm "$stderr_file"

# Determine the output file path
if [ -z "$OUTPUT_PATH" ]; then
    OUTPUT_DIR="/tmp"
    OUTPUT_BASE="job_output_$REGISTRY_NUMBER"
else
    OUTPUT_DIR=$(dirname "$OUTPUT_PATH")
    OUTPUT_BASE=$(basename "$OUTPUT_PATH" .stdout)
fi

ERROR_OCCURRED=0

# Check if the output directory exists
if [ ! -d "$OUTPUT_DIR" ]; then
    echo "ERROR: Output directory does not exist."
    ERROR_OCCURRED=1
else
    # Write stdout to file
    echo "$STDOUT" > "$OUTPUT_DIR/$OUTPUT_BASE.stdout"
    if [ $? -ne 0 ]; then
        echo "Error writing STDOUT to file."
        ERROR_OCCURRED=1
    fi

    # Write stderr to file
    echo "$STDERR" > "$OUTPUT_DIR/$OUTPUT_BASE.stderr"
    if [ $? -ne 0 ]; then
        echo "Error writing STDERR to file."
        ERROR_OCCURRED=1
    fi

    # Write exit code to file
    echo "$EXIT_CODE" > "$OUTPUT_DIR/$OUTPUT_BASE.exitcode"
    if [ $? -ne 0 ]; then
        echo "Error writing EXIT CODE to file."
        ERROR_OCCURRED=1
    fi
fi

# Show extracted values if an error occurred
if [ $ERROR_OCCURRED -ne 0 ]; then
    echo "Extracted stdout:"
    echo "$STDOUT"
    echo "Extracted stderr:"
    echo "$STDERR"
    echo "Extracted exit code:"
    echo "$EXIT_CODE"
    rm "$STATUS_TEMP_FILE"
    exit 7
fi

echo "Job output written to:"
echo "  STDOUT: $OUTPUT_DIR/$OUTPUT_BASE.stdout"
echo "  STDERR: $OUTPUT_DIR/$OUTPUT_BASE.stderr"
echo "  EXIT CODE: $OUTPUT_DIR/$OUTPUT_BASE.exitcode"

# Clean up
rm "$STATUS_TEMP_FILE"
