package lab01;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
import java.util.ArrayList;
import java.lang.String;

public class WSGenerator {

    //global variables
    static char[][] sopa;
    static String[][] register;
    static ArrayList<String> words = new ArrayList<String>();
    static ArrayList<String> wordLines = new ArrayList<>();
    static int wordID = 0;


    public static void main(String[] args) throws Exception {

        String inputFile = "", outputFile = "";
        int size = 0;
        String letters = "ABCDEFGHIJKLKMNOPQRSTUVWXYZ";

        if (args.length == 4 || args.length == 6) {
            for (int i=0; i<args.length; i++) {
                if (args[i].equals("-i")) 
                    inputFile = args[i+1];
                if (args[i].equals("-o"))
                    outputFile = args[i+1];
                if (args[i].equals("-s"))
                    size = Integer.parseInt(args[i+1]);
            }
        }
        else {
            System.out.println("Invalid command line arguments");
            System.exit(0);
        }


        if (!data(inputFile)) {
            System.out.println("Invalid");
            System.exit(0);
        }

        if (size > 40) {
            System.out.println("Invalid size");
            System.exit(0);
        }

        /* Fill sopa with dots */
        sopa = new char[size][size];
        for (int i=0; i<size; i++){
            for(int j=0; j<size; j++)
                sopa[i][j] = '.';
        }

        /* Fill register with "0" */
        register = new String[size][size];
        for (int i=0; i<size; i++) {
            for(int j=0; j<size; j++)
                register[i][j] = "";
        }

        /* Insert words */
        for (String word : words){  
            wordID++;
            insert(word, size);
        }

        /* Complete sopa */
        for (int i=0; i<size; i++){
            for(int j=0; j<size; j++) {
                if (sopa[i][j] == '.')
                    sopa[i][j] = letters.charAt( (int) (Math.random() * letters.length()));
            }
        } 

        if (outputFile.length() > 0) //if there is -o
            writeFile(outputFile, size);
        else {
            /* Print sopa */
            for (int i=0; i<size; i++){
                for(int j=0; j<size; j++)
                    System.out.printf("%c", sopa[i][j]);
                System.out.println();
            }
            for (String line : wordLines)
                System.out.println(line);
        }

    }

    public static boolean data(String fileName) throws IOException {
        File file = new File(fileName);
        Scanner sc = new Scanner(file);
        String line;
        int countMin = 0;


        while (sc.hasNextLine()){
            line = sc.nextLine();
            wordLines.add(line); //store the lines as they are to print them after the soup
            line = line.replaceAll("\\s", ";");
            line = line.replaceAll(",", ";");

            for(String s: line.split(";")){
                countMin = 0;
                for (int i=0; i<s.length(); i++)
                {
                    if (!Character.isUpperCase(s.charAt(i))) {countMin++;};
                    if (!Character.isLetter(s.charAt(i)))
                    {
                        sc.close();
                        return false;
                    }
                }
                if (countMin == 0){
                    sc.close();
                    return false;
                }
                    
                words.add(s);
            }
        }

        sc.close();
        return true;
    }
 
    public static void insert(String word, int size){

        int[] x = {1, -1, 0, 0, 1, -1, 1, -1};
        int[] y = {0, 0, -1, 1, -1, -1, 1, 1};
        int rand_x = 0;
        int rand_y = 0;
        int next_x, next_y;
        int rand_dir = 0;
        boolean condition1 = false;  //there is enough space to write the word (in a specific direction)
        boolean  condition2 = false; //word does not intersect the same word more than once
        String wordsID;              //register the id of words we intersect
        word = word.toUpperCase();

        while (!(condition1 && condition2)) {
            rand_x = (int) (Math.random() * size);
            rand_y = (int) (Math.random() * size);
            rand_dir = (int) (Math.random() * 8);
            wordsID = "";

            
            switch (rand_dir) {
                case 0:
                    condition1 = (size - rand_x) >= word.length();
                    break;


                case 1:
                    condition1 = (rand_x + 1) >= word.length();
                    break;

                case 2:
                    condition1 = (rand_y + 1) >= word.length();
                    break;

                case 3:
                    condition1 = (size - rand_y) >= word.length();
                    break;

                case 4:
                    condition1 = ((size - rand_x) >= word.length()) && ((rand_y + 1) >= word.length());
                    break;

                case 5:
                    condition1 = ((rand_x + 1) >= word.length()) && ((rand_y + 1) >= word.length());
                    break;

                case 6:
                    condition1 = ((size - rand_x) >= word.length()) && ((size - rand_y) >= word.length());
                    break;

                default:
                    condition1 = ((rand_x + 1) >= word.length()) && ((size - rand_y) >= word.length());
                   
            }

            if (!condition1)
                continue;
            
            next_x = rand_x;
            next_y = rand_y;

            for (int i=0; i<word.length(); i++) {
                if (sopa[next_y][next_x] == '.') {
                    next_x += x[rand_dir];
                    next_y += y[rand_dir];
                    condition2 = true;
                    continue;
                }
                else {
                    if (sopa[next_y][next_x] != word.charAt(i)) {
                        condition2 = false;
                        break;
                    }
                    else {
                        wordsID.concat(register[next_y][next_x]);  //register the word we are intersecting
                        condition2 = !moreThanTwo(wordsID, register[next_y][next_x]);
                        if (!condition2)
                            break;
                    }                    
                }

                next_x += x[rand_dir];
                next_y += y[rand_dir];
            }            
        }

        // aqui ja se encontrou uma posicao e direcao validas
        next_x = rand_x;
        next_y = rand_y;

        for (int i=0; i<word.length(); i++) {
            sopa[next_y][next_x] = word.charAt(i);
            register[next_y][next_x].concat(Integer.toString(wordID));
            next_x += x[rand_dir];
            next_y += y[rand_dir];
        }
    }

    public static boolean moreThanTwo(String wordsID, String words) {
        int total_times;

        for (int i=0; i<words.length(); i++) {
            total_times = 0;

            for (int j=0; j<wordsID.length(); j++) {
                if (words.charAt(i) == wordsID.charAt(j))
                    total_times++;
            }
            
            if (total_times >= 2)
                return true;
        }

        return false;
    }

    public static void writeFile(String outputFile, int size) throws IOException {
        FileWriter fileWriter = new FileWriter(outputFile);
        PrintWriter printWriter = new PrintWriter(fileWriter);

        for (int i=0; i<size; i++){
            for(int j=0; j<size; j++)
               printWriter.printf("%c",  sopa[i][j]);
            printWriter.printf("\n");
        } 
        for (String line : wordLines)
            printWriter.println(line);

        printWriter.close();
    }

}
