#!/bin/bash

SCRIPT=$( basename "$0" )

LINUX_HOST="${LINUX_SERVER:-localhost}:${LINUX_PORT:-1337}"
GAME_ID='0'
ROOM_ID='0'

if [[ -f 'gameid' && -s 'gameid' ]]; then
    GAME_ID=$(cat 'gameid')
fi

if [[ -f 'roomid' && -s 'roomid' ]]; then
    ROOM_ID=$(cat 'roomid')
fi

function usage
{
    local txt=(
        "Client script for the maze API."
        "Usage: $SCRIPT [options] <command> [arguments]"
        ""
        "Commands:"
        "  init             Initilizes a game and saves the game id to disk."
        "  maps             Shows the maps available."
        "  select [map]     Select map."
        "  enter            Enter the first room."
        "  info             Show info about the current room."
        "  go [direction]   Enters a room if available. Directions (north, south, east, west)."
        ""
        "Options:"
        "  -h, --help       Prints help."
        "  -v, --version    Prints version."
    )

    printf "%s\n" "${txt[@]}"
}

function badUsage
{
    local message="$1"
    local txt=(
        "For an overview of the command, execute:"
        "$SCRIPT --help"
    )

    [[ $message ]] && printf "$message\n"

    printf "%s\n" "${txt[@]}"
}

function version
{
    local txt=(
        "$SCRIPT version $VERSION"
    )

    printf "%s\n" "${txt[@]}"
}

# UTIL

function error_exit
{
    printf "$1" 1>&2
	exit 1
}

function loop_help
{
    local txt=(
        "You are using the loop function."
        ""
        "Commands:"
        "  help, h          Shows this help message."
        "  done             Exits the loop and the application."
        "  move [direction] Enters a room if available. Directions (north, south, east, west)."
    )

    printf "%s\n" "${txt[@]}"
}

function loop_bad_usage
{
    local txt=(
        "Enter command:('help' for help, 'done' to exit)"
    )

    printf "%s\n" "${txt[@]}"
}

function header_index
{
    local header=$(echo "$2" | head -n 1)
    local col_idx=-1

    IFS=, read -r -a fields <<< "$header"
    for index in "${!fields[@]}"; do
        if [[ "${fields[$index]}" = "$1" ]]; then
            col_idx=$(($index+1))
        fi
    done

    echo "$col_idx"
}

function get_value
{
    local col_idx=$(header_index $1 $2)
    local result=""

    if [ "$col_idx" != "-1" ]; then
        result=$(echo "$2" | tail -n 1 | cut -d ',' -f $col_idx)
    fi

    echo "$result"
}

function request
{
    local response=$(curl -s -w "%{http_code}" "$LINUX_HOST/$1?type=csv")

    echo "$response" > 'last.txt'

    local status=$(echo "$response" | tail -1)

    if [ "$status" = "000" ]; then
        echo 'ERR' >> 'last.txt'
        error_exit "An error occured, could not reach the server."
    fi

    echo "$status" >> 'last.txt'

    local content=$(echo "$response" | head -2)

    echo "$content" >> 'last.txt'

    if [ "$status" = "200" ]; then
        echo "$content"
        echo 'OK' >> 'last.txt'
    else
        echo 'ERR' >> 'last.txt'
        local text=$(get_value 'text' "$content")
        local hint=$(get_value 'hint' "$content")

        error_exit "$text\n$hint"
    fi
}

# APP

function app-init
{
    local data=$(request '')

    local id=$(get_value 'gameid' "$data")
    local text=$(get_value 'text' "$data")

    GAME_ID="$id"
    echo "$id" > 'gameid'
    echo "$text $id"
}

function app-maps
{
    local data=$(request 'map')

    IFS=, read -r -a maps <<< "$(echo "$data" | head -n 2 | tail -n 1)"
    for index in ${!maps[@]}; do
        printf "%s. %s\n" "$(($index+1))" "${maps[$index]}"
    done
}

function app-select
{
    local data=$(request "$GAME_ID/map/$1")

    echo $(get_value 'text' "$data")
}

function app-enter
{
    local data=$(request "$GAME_ID/maze")

    local id=$(get_value 'roomid' "$data")
    local description=$(get_value 'description' "$data")

    if [ "$id" != "" ]; then
        ROOM_ID="$id"
        echo "$id" > 'roomid'
    fi
}

function app-info
{
    local data=$(request "$GAME_ID/maze/$ROOM_ID")

    local directions=(
        $(get_value 'west' "$data")
        $(get_value 'east' "$data")
        $(get_value 'south' "$data")
        $(get_value 'north' "$data")
    )

    echo $(get_value 'description' "$data")
    echo ''
    echo 'Directions available'

    for index in ${!directions[@]}; do
        if [ "-" != "${directions[$index]}" ]; then
            case "$index" in
                0)
                    printf "%s\n" "west"
                ;;
                1)
                    printf "%s\n" "east"
                ;;
                2)
                    printf "%s\n" "south"
                ;;
                3)
                    printf "%s\n" "north"
                ;;
            esac
        fi
    done
}

function app-go
{
    local data=$(request "$GAME_ID/maze/$ROOM_ID/$1")

    local id=$(get_value 'roomid' "$data")
    local description=$(get_value 'description' "$data")

    if [ "$id" != "" ]; then
        ROOM_ID="$id"
        echo "$id" > 'roomid'
    fi
}

function app-loop
{
    app-init
    app-maps

    printf "\n%s" "Select map: "

    read -r selected
    local mapIndex=$(($selected-1))
    printf "%s\n" "You selectd: ${maps[$mapIndex]}"

    app-select "${maps[$mapIndex]}"
    app-enter
    app-info

    while IFS=' ' read -ra args; do
        case "${args[0]}" in
            help | h)
                loop_help
            ;;
            done)
                break
            ;;
            move)
                app-go "${args[1]}"
                app-info
            ;;
            *)
                loop_bad_usage
            ;;
        esac
    done
}

# START

while (( $# ))
do
    case "$1" in
        --help | -h)
            usage
            exit 0
        ;;
        --version | -v)
            version
            exit 0
        ;;
        init \
        | maps \
        | select \
        | enter \
        | info \
        | go \
        | loop)
            command=$1
            shift
            app-$command $*
            exit 0
        ;;
        *)
            badUsage "Option/command not recognized."
            exit 1
        ;;
    esac
done
