package dotsandboxes;

import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;

public class DotsAndBoxesUI {

    final int lineLength = 32;
    final int margin = 10;
    final int gap = 0;
    final int dotDiameter = 6;

    final DotsAndBoxesGrid grid;
    final AnchorPane anchorPane;
    final Label label;

    /** Colours for the different players. Only goes up to 5. */
    final Color[] playerColours = { Color.WHITE, Color.RED, Color.BLUE, Color.GREEN, Color.PURPLE, Color.ORANGE };

    private void updateLabel() {
        label.setTextFill(playerColours[grid.getPlayer()]);
        label.setText(String.format("Player %d's turn", grid.getPlayer()));
    }

    public DotsAndBoxesUI(final DotsAndBoxesGrid grid) {
        this.grid = grid;
        anchorPane = new AnchorPane();

        label = new Label("");
        updateLabel();
        grid.addConsumer((g) -> updateLabel());

        // Size the anchorPane to just contain the elements
        int width = margin + dotDiameter + gap + (grid.width - 1) * (gap + lineLength + gap + dotDiameter) + gap + margin;
        int height = margin + dotDiameter + gap + (grid.height - 1) * (gap + lineLength + gap + dotDiameter) + gap + margin;
        anchorPane.setPrefSize(width, height);


        // Lay out the boxes
        for (int row = 0; row < grid.height - 1; row++) {
            for (int col = 0; col < grid.width - 1; col++) {
                final int x = col;
                final int y = row;
                Rectangle box = new Rectangle(gap, gap, lineLength, lineLength);
                box.setFill(Color.WHITE);

                grid.addConsumer((g) -> {
                    box.setFill(playerColours[g.getBoxOwner(x, y)]);
                });

                AnchorPane.setLeftAnchor(box, gap + dotDiameter + col * (gap + lineLength + gap + dotDiameter) + dotDiameter/2.0);
                AnchorPane.setTopAnchor(box, gap + dotDiameter + row * (gap + lineLength + gap + dotDiameter) + dotDiameter/2.0);
                anchorPane.getChildren().add(box);
            }
        }

        // Lay out the horizontals
        for (int row = 0; row < grid.height; row++) {
            for (int col = 0; col < grid.width - 1; col++) {
                Line line = new Line(0, dotDiameter/2.0, lineLength, dotDiameter/2.0);
                line.setStrokeWidth(dotDiameter);
                line.setStroke(Color.DARKGREY);

                final int x = col;
                final int y = row;
                grid.addConsumer((g) -> {
                    if (g.getHorizontal(x, y)) {
                        line.setStroke(Color.BLACK);
                    } else {
                        line.setStroke(Color.LIGHTGRAY);
                    }
                });

                line.setOnMouseClicked((evt) -> {try {
                    grid.drawHorizontal(x, y, grid.getPlayer());
                } catch (IllegalStateException ex) {
                    // do nothing
                    // This is a little artificial, as normally we'd implement this with a check that the line isn't
                    // already "drawn" and then not calling the function. But for the exercise, we wanted students
                    // to write a test that would ensure an exception is thrown, so we're relying on an exception
                    // being thrown!
                }});

                AnchorPane.setLeftAnchor(line, 0.0 + gap + dotDiameter + col * (gap + lineLength + gap + dotDiameter));
                AnchorPane.setTopAnchor(line, -dotDiameter/2.0 + gap + dotDiameter + row * (gap + lineLength + gap + dotDiameter));
                anchorPane.getChildren().add(line);
            }
        }

        // Lay out the verticals
        for (int row = 0; row < grid.height - 1; row++) {
            for (int col = 0; col < grid.width; col++) {
                Line line = new Line(-dotDiameter/2.0, 0, -dotDiameter/2.0, lineLength);
                line.setStrokeWidth(dotDiameter);
                line.setStroke(Color.DARKGREY);

                final int x = col;
                final int y = row;
                grid.addConsumer((g) -> {
                    if (g.getVertical(x, y)) {
                        line.setStroke(Color.BLACK);
                    } else {
                        line.setStroke(Color.LIGHTGRAY);
                    }
                });

                line.setOnMouseClicked((evt) -> {try {
                    grid.drawVertical(x, y, grid.getPlayer());
                } catch (IllegalStateException ex) {
                    // do nothing
                }});

                AnchorPane.setTopAnchor(line, 0.0 + gap + dotDiameter + row * (gap + lineLength + gap + dotDiameter));
                AnchorPane.setLeftAnchor(line, -dotDiameter/2.0 + gap + dotDiameter + col * (gap + lineLength + gap + dotDiameter));
                anchorPane.getChildren().add(line);
            }
        }

        // Lay out the dots
        for (int row = 0; row < grid.height; row++) {
            for (int col = 0; col < grid.width; col++) {
                Circle dot = new Circle(dotDiameter / 2.0);
                dot.setFill(Color.YELLOW);

                AnchorPane.setLeftAnchor(dot, gap + col * (gap + lineLength + gap + dotDiameter) + dotDiameter/2.0);
                AnchorPane.setTopAnchor(dot, gap + row * (gap + lineLength + gap + dotDiameter) + dotDiameter/2.0);
                anchorPane.getChildren().add(dot);
            }
        }

    }



}