//PDS Prático 2023 - Guião 1 - 1.2
//G5_05
import java.util.*;
import java.io.*;

public class WSGenerator {

	//Função principal para gerar a sopa de letras a partir da linha de comando:
    public static void main(String[] args) {
        String inputFile = "";
        String outputFile = "";
        int size = 0;

        // Analisar a linha de comandos
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-i")) {
                inputFile = args[++i];
            } else if (args[i].equals("-o")) {
                outputFile = args[++i];
            } else if (args[i].equals("-s")) {
                size = Integer.parseInt(args[++i]);
            }
        }

        // Ler a lista de palavras do arquivo de entrada
        List<String> words = readWordsFromFile(inputFile);

        // Limitar o tamanho da sopa de letras a 40
        if (size > 40) {
            System.out.println("Tamanho da sopa de letras muito grande. Usando tamanho máximo de 40.");
            size = 40;
        }

        // Gerar a sopa de letras
        char[][] soup = generateSoup(words, size);

        // Escrever a sopa de letras no arquivo de saída, se especificado
        try {
            if (!outputFile.equals("")) {
                writeSoupToFile(soup, outputFile,words);
            } else {
                for (int i = 0; i < soup.length; i++) {
                    for (int j = 0; j < soup.length; j++) {
                        System.out.print(Character.toUpperCase(soup[i][j]));
                    }
                    System.out.println();
                }
                for (int p = 0; p < words.size(); p++) {
                    System.out.print(words.get(p).toLowerCase());
                    System.out.print(";");
                }
                System.out.println();
            }
        } catch (IOException e) {
            System.out.println("Erro ao escrever a sopa de letras no arquivo.");
            e.printStackTrace();
        }
    }

    //Função ler ficheiro de input
    private static List<String> readWordsFromFile(String fileName) {
        List<String> words = new ArrayList<>();
        try (Scanner scanner = new Scanner(new File(fileName))) {
            while (scanner.hasNextLine()) {
                String word = scanner.nextLine().trim();
                if (!word.isEmpty()) {
                    if (word.length() >= 3) {//Verificar que palavra cumpre requisitos de mais de 3 letras
                        if (!words.contains(word)) {//Verificar que palavra não é repetida
                            words.add(word);
                        } else {
                            System.out.println("Palavra ignorada por ser repetida: " + word);
                        }
                    } else {
                        System.out.println("Palavra ignorada por ser pequena demais (<3 de letras): " + word);
                    }
                }
            }
        } catch (IOException e) {
            System.out.println("Erro ao ler o ficheiro " + fileName);
        }
        return words;
    }

    // Função para gerar a sopa de letras (8 direçoes!):
    private static char[][] generateSoup(List<String> words, int size) {
        // Inicializar a sopa de letras com espaços em branco
        char[][] soup = new char[size][size];
        for (int i = 0; i < size; i++) {
            Arrays.fill(soup[i], ' ');
        }

        // Inserir as palavras na sopa de letras
        Random random = new Random();
        for (String word : words) {
            int wordLength = word.length();
            boolean inserted = false;
            while (!inserted) {
                // Escolher uma direção aleatória para inserir a palavra
                int dx, dy;
                do {//Não podem ser 0
                    dx = random.nextInt(3) - 1;
                    dy = random.nextInt(3) - 1;
                } while (dx == 0 && dy == 0);

                // Escolher a posição inicial da palavra
                int x = random.nextInt(size - (wordLength - 1) * Math.abs(dx));
                int y = random.nextInt(size - (wordLength - 1) * Math.abs(dy));

                // Tentar inserir a palavra na sopa de letras
                boolean canInsert = true;
                for (int j = 0; j < wordLength; j++) {
                    int cx = x + j * dx;
                    int cy = y + j * dy;
                    if (cx < 0 || cx >= size || cy < 0 || cy >= size) {
                        canInsert = false;
                        break;
                    }
                    if (soup[cx][cy] != ' ' && soup[cx][cy] != word.charAt(j)) {
                        canInsert = false;
                        break;
                    }
                }

                // Inserir a palavra se for possível, ou tentar novamente com outra direção e posição
                if (canInsert) {
                    for (int j = 0; j < wordLength; j++) {
                        int cx = x + j * dx;
                        int cy = y + j * dy;
                        soup[cx][cy] = word.charAt(j);
                    }
                    inserted = true;
                }
            }
        }

        // Preencher o resto da sopa de letras com letras aleatórias
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (soup[i][j] == ' ') {
                    soup[i][j] = (char) ('a' + random.nextInt(26));
                }
            }
        }

        return soup;
    }



    //Função para escrever a sopa de letras em um arquivo:
    private static void writeSoupToFile(char[][] soup, String filename, List<String> words) throws IOException {
        FileWriter writer = new FileWriter(filename);
        for (int i = 0; i < soup.length; i++) {//Escrever sopa de letras
            for (int j = 0; j < soup.length; j++) {
                writer.write(Character.toUpperCase(soup[i][j]));
            }
            writer.write("\n");
        }
        for (int i = 0; i < words.size(); i++) {//Escrever palavras separadas por ';'
            writer.write(words.get(i).toLowerCase());
            writer.write(";");
        }
        writer.close();
    }
}