import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

/*
Todos:
1. Create an 'Island' class  ✓
*/

public class RecursiveIslandDriver {

    // Ocean dimensions
    public static final int NUMROWS = 10;
    public static final int NUMCOLS = 20;

    // Island size constraints -- every island placed in the ocean
    // will have a randomly chosen size somewhere in this range.
    public static final int MIN_ISLAND_SIZE = 5;
    public static final int MAX_ISLAND_SIZE = 20;

    // The ocean is a 2D array of integers.
    //   0 = water
    //   1 = land (part of an island)
    private static int[][] ocean = new int[NUMROWS][NUMCOLS];

    public static void main(String[] args) {
        System.out.println("=== Recursive Island ===");
        System.out.println("Ocean size    : " + NUMROWS + " rows x " + NUMCOLS + " columns");
        System.out.println("Island sizes  : " + MIN_ISLAND_SIZE + " to " + MAX_ISLAND_SIZE + " cells");
        System.out.println();

        Scanner kb  = new Scanner(System.in);
        Random  rand = new Random();

        // --- Get user input: how many islands to place ---
        System.out.print("How many islands would you like to place? ");
        int requestedCount = kb.nextInt();

        // Basic validation: must request at least one island
        if (requestedCount <= 0) {
            System.out.println("Please enter a positive number.  Goodbye!");
            kb.close();
            return;
        }

        // --- ArrayList to collect every successfully placed Island ---
        // We use ArrayList because we don't know ahead of time how many
        // islands will actually fit (some attempts may fail).
        ArrayList<Island> placedIslands = new ArrayList<>();

        System.out.println();

        // --- Try to place each island one at a time ---
        for (int i = 0; i < requestedCount; i++) {

            // Pick a random target size in [MIN_ISLAND_SIZE, MAX_ISLAND_SIZE].
            // rand.nextInt(n) returns a value in [0, n-1], so we shift by MIN.
            int targetSize = MIN_ISLAND_SIZE
                             + rand.nextInt(MAX_ISLAND_SIZE - MIN_ISLAND_SIZE + 1);

            System.out.println("Placing island " + (i + 1) + " of " + requestedCount
                               + "  (target size: " + targetSize + " cells)...");

            // Island.buildIsland() uses the RECURSIVE BACKTRACKING algorithm
            // in Island.grow() to find a valid spot and shape for the island.
            // It returns null if no valid placement could be found.
            Island newIsland = Island.buildIsland(ocean, targetSize, NUMROWS, NUMCOLS, rand);

            if (newIsland != null) {
                // Island was placed successfully -- save it
                placedIslands.add(newIsland);
                System.out.println("  Placed!  " + newIsland);
            } else {
                // buildIsland exhausted all attempts without success
                System.out.println("  Could not place island " + (i + 1)
                                   + " -- the ocean may be too crowded.");
            }
        }

        // --- Print the ocean grid ---
        System.out.println("\n=== Ocean Map  (0 = water,  1 = land) ===");
        printTheOcean();

        // --- Print a summary of what was placed ---
        System.out.println("\n=== Island Summary ===");
        System.out.println("Successfully placed: " + placedIslands.size()
                           + " of " + requestedCount + " requested islands.");
        System.out.println();
        for (int i = 0; i < placedIslands.size(); i++) {
            System.out.println("  Island " + (i + 1) + ": " + placedIslands.get(i));
        }

        // --- Ask the user if they want to save the ocean to a file ---
        // We consume the leftover newline from nextInt() before calling nextLine().
        kb.nextLine();
        System.out.print("\nWould you like to save the ocean to a file? (yes/no): ");
        String saveChoice = kb.nextLine().trim().toLowerCase();

        if (saveChoice.equals("yes") || saveChoice.equals("y")) {
            // saveOceanToFile() builds a time-stamped filename automatically.
            saveOceanToFile(placedIslands);
        }

        kb.close();
        System.out.println("\nGoodbye! Thanks for using our program!");
    }//end main

    /**
     * Saves the current ocean grid and island summary to a text file.
     *
     * FILE NAMING:
     *   The filename is built automatically using the current date and time
     *   so that every saved file has a unique name and you can tell exactly
     *   when it was created.  Format: ocean_YYYYMMDD_HHmmss.txt
     *   Example: ocean_20260315_143022.txt
     *
     *   LocalDateTime.now() -- returns the current date/time from the system clock
     *   DateTimeFormatter   -- controls how the date/time is formatted as a String
     *
     * FILE WRITING:
     *   PrintWriter wraps a FileWriter, which opens (or creates) the file.
     *   PrintWriter gives us println() / printf() just like System.out,
     *   making it easy to write formatted text.
     *   The try-with-resources block (try (...) { }) automatically closes
     *   the file when we're done, even if an exception is thrown.
     *
     * @param placedIslands  the list of islands to include in the summary section
     */
    private static void saveOceanToFile(ArrayList<Island> placedIslands) {

        // Build the time-stamped filename.
        // DateTimeFormatter.ofPattern() takes a pattern string where:
        //   yyyy = 4-digit year,  MM = 2-digit month,  dd = 2-digit day
        //   HH   = 24-hour hour,  mm = minutes,        ss = seconds
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
        String timestamp = LocalDateTime.now().format(formatter);
        String filename  = "ocean_" + timestamp + ".txt";

        // try-with-resources: Java will automatically call writer.close() for us.
        // This is important -- if we forget to close a file, data can be lost!
        try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {

            // ── Header ──────────────────────────────────────────────
            writer.println("=== Recursive Island Save File ===");
            writer.println("Saved on: " + LocalDateTime.now()
                           .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            writer.println("Ocean size: " + NUMROWS + " rows x " + NUMCOLS + " columns");
            writer.println();

            // ── Ocean grid ──────────────────────────────────────────
            writer.println("=== Ocean Map  (0 = water,  1 = land) ===");
            for (int r = 0; r < NUMROWS; r++) {
                for (int c = 0; c < NUMCOLS; c++) {
                    writer.print(ocean[r][c] + " ");
                }
                writer.println();
            }
            writer.println();

            // ── Island summary ──────────────────────────────────────
            writer.println("=== Island Summary ===");
            writer.println("Total islands placed: " + placedIslands.size());
            writer.println();
            for (int i = 0; i < placedIslands.size(); i++) {
                writer.println("  Island " + (i + 1) + ": " + placedIslands.get(i));
            }

            // Let the user know where to find the file.
            System.out.println("Ocean saved to: " + filename);

        } catch (IOException e) {
            // IOException is thrown if the file cannot be created or written to.
            // This could happen if the disk is full, permissions are denied, etc.
            System.out.println("Error saving file: " + e.getMessage());
        }
    }//end saveOceanToFile

    //no-touch code
    private static void printTheOcean() {
        for (int r = 0; r < NUMROWS; r++) {
            for (int c = 0; c < NUMCOLS; c++) {
                System.out.print(ocean[r][c] + " ");
            }
            System.out.println();
        }
    }//end printTheOcean

}//end class


