package com.lastabyss.psciv.dungeon;

import com.lastabyss.psciv.util.Util;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author Navid
 */
class TestDungeonAlgorithm extends Application {

    private Stage stage;
    private Pane root;
    private ScheduledThreadPoolExecutor thread;

    private final List<Rectangle> generatedRooms = new ArrayList<>();

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        root = new Pane();
        root.setStyle("-fx-background-color: darkslategrey; -fx-border-color: black; -fx-border-width: 3px");
        Scene scene = new Scene(root, 1280, 720);
        primaryStage.setTitle("Test Dungeon Algorithm");
        primaryStage.setScene(scene);
        primaryStage.show();
        this.stage = primaryStage;
        List<Rectangle> rooms = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            rooms.add(new Rectangle(Util.random.nextInt(100) + 50, Util.random.nextInt(100) + 50));
        }

        scene.setOnKeyPressed((evt) -> {
            if (evt.getCode() == KeyCode.R) {
                root.getChildren().clear();
                generate(10, rooms);
            }
        });
    }

    private void generate(int iterations, List<Rectangle> rooms) {
        generatedRooms.clear();
        if (thread != null)
            thread.shutdownNow();
        thread = new ScheduledThreadPoolExecutor(1);
        Collections.shuffle(rooms, Util.random);
        int arrPos = 0;
        for (int i = 0; i < iterations; i++) {
            if (arrPos > rooms.size() - 1) arrPos = 0;
            Rectangle org = rooms.get(arrPos);
            Rectangle rect = new Rectangle(org.getWidth(), org.getHeight());
            rect.setId("Room " + i);
            rect.setFill(Paint.valueOf(Color.WHITE.toString()));
            rect.setStroke(Paint.valueOf(Color.GREEN.toString()));
            rect.setLayoutX(Util.random.nextInt(1280));
            rect.setLayoutY(Util.random.nextInt(720));
            if (rect.getWidth() * rect.getHeight() < 200) continue;
            root.getChildren().add(rect);
            if (!contains(rect)) {
                thread.schedule(() -> Platform.runLater(() -> {
                    root.getChildren().remove(rect);
                    generatedRooms.remove(rect);
                }), generatedRooms.size() + 5, TimeUnit.SECONDS);
            } else {
                checkOverlap(rect);
            }
            System.out.println("added " + rect.getId());
            arrPos++;
        }
    }

    private void checkOverlap(Rectangle room) {
        boolean isOverlapping = false;
        for (Rectangle r : generatedRooms) {
            if (r != room) {
                Shape intersect = Shape.intersect(r, room);
                if (intersect.getBoundsInLocal().getWidth() != -1) {
                    isOverlapping = true;
                }
            }
        }
        if (isOverlapping) {
            room.setFill(Paint.valueOf(Color.RED.toString()));
            thread.schedule(() -> Platform.runLater(() -> {
                root.getChildren().remove(room);
                generatedRooms.remove(room);
            }), generatedRooms.size() * 50, TimeUnit.MILLISECONDS);
        } else {
            generatedRooms.add(room);
        }
    }

    private boolean contains(Rectangle rectangle) {
        Bounds bounds = rectangle.getBoundsInParent();
        if (root.contains(bounds.getMinX(), bounds.getMinY()) &&
                root.contains(bounds.getMaxX(), bounds.getMaxY())) return true;
        rectangle.setFill(Paint.valueOf(Color.BLACK.toString()));
        return false;
    }
}
