#!/bin/bash

set -u

__robot_direction=u
__robot_lowest_x=0
__robot_lowest_y=0
__robot_highest_x=0
__robot_highest_y=0
__robot_cur_x=0
__robot_cur_y=0
__robot_start_on_white=0
declare -A __robot_grid
declare -A __robot_painted

reset_robot() {
    __robot_direction=u
    __robot_lowest_x=0
    __robot_lowest_y=0
    __robot_highest_x=0
    __robot_highest_y=0
    __robot_cur_x=0
    __robot_cur_y=0
    __robot_start_on_white=0
    unset __robot_grid
    unset __robot_painted
    declare -g -A __robot_grid
    declare -g -A __robot_painted
}

get_robot_paint_colour() {
    get_paint_colour $__robot_cur_x $__robot_cur_y
}

get_paint_colour() {
    x=$1
    y=$2

    if [ ${__robot_grid[$x,$y]+a} ]; then
        echo ${__robot_grid[$x,$y]}
    else
        if [ $x -eq 0 ] && [ $y -eq 0 ] && [ $__robot_start_on_white -eq 1 ]; then
            echo 1
        else
            echo 0
        fi
    fi
}

set_robot_start_on_white() {
    start=${1:-1}

    __robot_start_on_white=$start
}

set_robot_paint_colour() {
    paint_colour=$1

    __robot_grid[$__robot_cur_x,$__robot_cur_y]=$paint_colour
    if ! [ ${__robot_painted[$__robot_cur_x,$__robot_cur_y]+a} ]; then
        __robot_painted[$__robot_cur_x,$__robot_cur_y]=1
    fi
}

get_robot_paint_count() {
    echo ${#__robot_painted[@]}
}

do_robot_move() {
    direction=$1

    case $direction in
        0)
            case $__robot_direction in
                u)
                    __robot_direction=l
                    __robot_cur_x=$((__robot_cur_x - 1))
                    ;;
                l)
                    __robot_direction=d
                    __robot_cur_y=$((__robot_cur_y - 1))
                    ;;
                d)
                    __robot_direction=r
                    __robot_cur_x=$((__robot_cur_x + 1))
                    ;;
                r)
                    __robot_direction=u
                    __robot_cur_y=$((__robot_cur_y + 1))
                    ;;
            esac
            ;;
        1)
            case $__robot_direction in
                u)
                    __robot_direction=r
                    __robot_cur_x=$((__robot_cur_x + 1))
                    ;;
                r)
                    __robot_direction=d
                    __robot_cur_y=$((__robot_cur_y - 1))
                    ;;
                d)
                    __robot_direction=l
                    __robot_cur_x=$((__robot_cur_x - 1))
                    ;;
                l)
                    __robot_direction=u
                    __robot_cur_y=$((__robot_cur_y + 1))
                    ;;
            esac
            ;;
    esac

    # adjust min/max
    if [ $__robot_cur_x -lt $__robot_lowest_x ]; then
        __robot_lowest_x=$__robot_cur_x
    fi

    if [ $__robot_cur_x -gt $__robot_highest_x ]; then
        __robot_highest_x=$__robot_cur_x
    fi

    if [ $__robot_cur_y -lt $__robot_lowest_y ]; then
        __robot_lowest_y=$__robot_cur_y
    fi

    if [ $__robot_cur_y -gt $__robot_highest_y ]; then
        __robot_highest_y=$__robot_cur_y
    fi
}

do_robot_paint_and_move() {
    paint_colour=$1
    direction=$2
    set_robot_paint_colour $paint_colour
    do_robot_move $direction
}

draw_panel() {
    colours=("." "#")

    # we draw upside down, in effect, starting from the bottom and going to
    # the top, so when outputting, we should switch that round
    for (( y=$__robot_highest_y; y>=$__robot_lowest_y; y-- )); do
        for (( x=$__robot_lowest_x; x<=$__robot_highest_x; x++ )); do
            echo -n ${colours[$(get_paint_colour $x $y)]}
        done
        echo
    done
}
