import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;

public class RobotStandIn implements RobotBehavior {
    private final int ROWS = 12;
    private final int COLUMNS = 15;
    private String name;
    private int row;
    private int column;
    private CompassDirection facing;
    private String[][] board;
    private ArrayList<String> holding;
    
    private static Random random = new Random();

    public RobotStandIn(String name, int row, int column,
                        CompassDirection facing) {
        this.name = name;
        this.row = row;
        this.column = column;
        this.facing = facing;
        // Place robot
        board = new String[ROWS][COLUMNS];
        if (row <= 0 || row >= ROWS - 1 
                || column <= 0 || column >= COLUMNS - 1) {
            throw new IllegalArgumentException(
                "Illegal position: " + row + " " + column);
        }
        // Build walls
        for (int i = 0; i < ROWS; i++) {
            board[i][0] = "WALL";
            board[i][COLUMNS - 1] = "WALL";
        }
        for (int j = 0; j < COLUMNS; j++) {
            board[0][j] = "WALL";
            board[ROWS - 1][j] = "WALL";
        }
        // Put some objects
        int numberOfThings = Math.min(12, (ROWS - 2) * (COLUMNS - 2));
        for (int i = 1; i < numberOfThings; i++) {
            int thingRow = random.nextInt(ROWS - 2) + 1;
            int thingColumn = random.nextInt(COLUMNS - 2) + 1;
            if (board[thingRow][thingColumn] != null) continue;
            
            if (i % 4 == 0) {
                board[thingRow][thingColumn] = "FUEL";
            }
            else if (i % 4 == 1) {
                board[thingRow][thingColumn] = "ARMOR";
            }
            else if (i % 4 == 2) {
                board[thingRow][thingColumn] = "ZAP_GUN";
            }
            else {
                board[thingRow][thingColumn] = "ENEMY";
            }
        }
        print();
        System.out.println("Created " + name + " at " + location() + ".");
        holding = new ArrayList<String>();
    }

    public void drop(String thing) {
        if (holding.remove(thing)) {
            board[row][column] = thing;
            System.out.println(name + " drops " + thing + " at " + location());
        }
        else {
            System.out.println(name + " isn't holding " + thing);
        }
    }

    public boolean facing(String direction) {
        if (facing.toString().equalsIgnoreCase(direction)) {
            System.out.println("Yes, " + name + " is facing " + direction);
            return true;
        }
        else {
            System.out.println("No, " + name + " is not facing " + direction);
            return false;
        }
    }

    public int getColumn() {
        System.out.println(name + " is in column " + column);
        return column;
    }

    public int getDistance() {
        int[] location = locationOfNextThing();
        int distance = Math.abs(row - location[0] + column - location[1]);
        System.out.println("The distance to something is " + distance);
        return distance;
    }

    public int getRow() {
        System.out.println(name + " is in row " + row);
        return row;
    }

    public void move(int howFar) {
        int deltaRow = facing.getDeltaRow();
        int deltaColumn = facing.getDeltaColumn();
        int nextRow = row;
        int nextColumn = column;
        int moves = 0;
        boolean stopped = false;
        String thing = "";
        
        for (int i = 0; i < howFar; i++) {
            nextRow += deltaRow;
            nextColumn += deltaColumn;
            thing = board[nextRow][nextColumn];
            if ("WALL".equals(thing) || "ENEMY".equals(thing)) {
                stopped = true;
                break;
            }
            row = nextRow;
            column = nextColumn;
            moves++;
        }
        System.out.print(name + " moves ahead " + moves 
                         + " squares, to " + location());
        if (stopped) System.out.println("; stopped by " + thing);
        else System.out.println();
    }

    public boolean seeing(String thing) {
        int[] location = locationOfNextThing();
        String seenThing = board[location[0]][location[1]] + "";
        if (thing.equals(seenThing)) {
            System.out.println("Yes, " + name + " sees a " + thing);
            return true;
        }
        else {
            System.out.println("No, " + name + " doesn't see a " + thing);
            return false;
        }
    }

    public boolean smelling(String thing) {
        for (int i = row - 1; i <= row + 1; i++) {
            for (int j = column - 1; j <= column + 1; j++) {
                if (thing.equals(board[i][j])) {
                    System.out.println("Yes, " + name + " smells a " + thing);
                    return true;
                }
            }
        }
        System.out.println("No, " + name + " doesn't smell a " + thing);
        return false;
    }

    public void take(String thing) {
        if (thing.equals(board[row][column])) {
            System.out.println(name + " takes a " + thing + " from " + location());
            board[row][column] = null;
            holding.add(thing);
        }
        else {
            System.out.println("There is no " + thing + " here at " + location());
        }
    }

    public void turnAround() {
        facing = facing.getAround();
        System.out.println(name + " turns around, to face " + facing);
    }

    public void turnEast() {
        facing = CompassDirection.EAST;
        System.out.println(name + " turns to face " + facing);
    }

    public void turnLeft() {
        facing = facing.getLeft();
        System.out.println(name + " turns left, to face " + facing);
    }

    public void turnNorth() {
        facing = CompassDirection.NORTH;
        System.out.println(name + " turns to face " + facing);
    }

    public void turnRight() {
        facing = facing.getRight();
        System.out.println(name + " turns right, to face " + facing);
    }

    public void turnSouth() {
        facing = CompassDirection.SOUTH;
        System.out.println(name + " turns to face " + facing);
    }

    public void turnWest() {
        facing = CompassDirection.WEST;
        System.out.println(name + " turns to face " + facing);
    }

    public void zap() {
        if (!holding.contains("ZAP_GUN")) {
            System.out.println(name + " doesn't have a zap gun");
            return;
        }
        int[] location = locationOfNextThing();
        String thing = board[location[0]][location[1]];
        System.out.println(name + " zaps the " + thing + " at (" +
                           location[0] + ", " + location[1] + ")");
        if (!thing.equals("WALL")) {
            board[location[0]][location[1]] = null;
        }
    }
    
    public void print() {
        for (int i = 0; i < ROWS; i++) {
            for (int j = 0; j < COLUMNS; j++) {
                printCell(board[i][j], row == i && column == j);
            }
            System.out.println();
        }
    }
    
    private void printCell(String contents, boolean robotIsHere) {
        String robotMarker = " ";
        if (robotIsHere) {
            if (facing == CompassDirection.NORTH) robotMarker = "^";
            else if (facing == CompassDirection.EAST) robotMarker = ">";
            else if (facing == CompassDirection.SOUTH) robotMarker = "v";
            else if (facing == CompassDirection.WEST) robotMarker = "<";
        }
        char thingMarker = '.';
        if (contents != null) thingMarker = contents.charAt(0);
        System.out.print(" " + thingMarker + robotMarker + " ");
    }

    private String location() {
        return "(" + row + ", " + column + ")";
    }
    
    private int[] locationOfNextThing() {
        int deltaRow = facing.getDeltaRow();
        int deltaColumn = facing.getDeltaColumn();
        int nextRow = row;
        int nextColumn = column;
        do {
            nextRow += deltaRow;
            nextColumn += deltaColumn;
        } while (board[nextRow][nextColumn] == null);
        return new int[] { nextRow, nextColumn };
    }
}
