public class Swapper {

    private Robot robot;
    private static final int DELAY = 150;

    public static void main(String[] args) {
        Swapper swap = new Swapper();
        swap.createEnviroment();
        swap.swapAll();
    }

    private void createEnviroment() {
        RobotWorld world = RobotWorld.load("src/swap.txt");
        robot = new Robot(1, world.getNumCols() / 2 , Robot.SOUTH, world);
        robot.setDelay(DELAY);
    }

    // swapAll() swaps the cells to the left and the right of the corridor.
    // Precondition: the robot is at the start of a corridor of width 3.
    // Postconditions:
    // • The robot is at the end of the corridor
    // • All rows with a dark square on one side and a dark square on the
    //   other side have been swapped.
    public void swapAll() {
        while (!atEndOfCorridor()) {
            swapTwoCells();
            robot.move();
        }
        swapTwoCells();
    }

    // swapTwoCells() swaps the cells to the left and the right of the robot.
    // Precondition: there are open squares to the left and the right of the
    // robot.
    // Postconditions:
    // • The colors of the squares to the left and the right of the robot are
    //   swapped.
    // • The robot is in the same position as where it started.
    private void swapTwoCells() {
        if (areColorsDifferent()) {
            changeColorOfLeft();
            changeColorOfRight();
        }
    }

    // areColorsDifferent() checks if colors to the left and right of the
    // robot are different.
    // Precondition: there are open squares to the left and the right.
    // Postconditions:
    // • The result is true iff the left cell is light and the right cell is
    //   dark or vice versa.
    // • The robot is in the same position as where it started.
    private boolean areColorsDifferent() {
        robot.turnLeft();
        robot.move();
        boolean leftIsDark = robot.onDark();
        turnAround();
        moveSteps(2);
        boolean rightIsDark = robot.onDark();
        turnAround();
        moveSteps(1);
        turnRight();
        return leftIsDark ^ rightIsDark;
    }

    private void turnAround() {
        robot.turnLeft();
        robot.turnLeft();
    }

    private void turnRight() {
        turnAround();
        robot.turnLeft();
    }

    private void moveSteps(int i) {
        for (int k = 0; k < i; k++) {
            robot.move();
        }
    }

    // changeColorOfLeft() changes the color of the cell to the left of the
    // robot.
    // Precondition: there is an open square to the left of the robot.
    // Postconditions:
    // • The color of the cell to the left of the robot
    //   has changed from light to dark or vice versa.
    // • The robot is in the same position as where it started.
    private void changeColorOfLeft() {
        robot.turnLeft();
        robot.move();
        changeColor();
        turnAround();
        robot.move();
        robot.turnLeft();
    }

    // changeColorOfRight() changes the color of the cell to the right of the
    // robot.
    // Precondition: there is an open square to the right of the robot.
    // Postconditions:
    // • The color of the cell to the right of the robot
    //   has changed from light to dark or vice versa.
    // • The robot is in the same position as where it started.
    private void changeColorOfRight() {
        turnRight();
        robot.move();
        changeColor();
        turnAround();
        robot.move();
        turnRight();
    }

    // changeColor() changes the color of the cell at the current position of
    // the robot.
    // Precondition: none
    // Postconditions:
    // • The color of the cell at the current position of the robot has
    //   changed from light to dark or vice versa.
    // • The robot is in the same position as where it started.
    private void changeColor() {
        if (robot.onDark()) {
            robot.makeLight();
        } else {
            robot.makeDark();
        }
    }

    // atEndOfCorridor() checks if the robot is at the end of the corridor.
    // Precondition: none
    // Postcondition: the result is true iff the robot is at the end of the
    // corridor.
    private boolean atEndOfCorridor() {
        return !robot.frontIsClear();
    }

}