package school_project.Parsers;

import javafx.util.Pair;
import school_project.Map;
import school_project.Piece;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.NotSerializableException;
import java.util.Scanner;

/**
 * This is used to find the right parser to parser a save/level file.
 * This should be the only right way to save/load a file! you can just use `Map loadMapFromFile(File)` to load a file
 * and `void saveFileFromMap(File, Map)` to save a file
 *
 * <p>
 * there is currently 2 file format with 2 variation each (save file or level file)
 * - BinaryParser
 *  - ".level"
 *  - ".slevel"
 * - SerializeParser
 *  - ".serialized"
 *  - ".sserialized"
 * </p>
 *
 * <p>
 * More file format can be added in the future by adding a new class that implement parser
 * and adding it to this file
 * </p>
 *
 * @author tonitch
 */
public class FileParserFactory {
    /**
     * Load a file and return a map
     * If this is a save map, return the map with its save data
     * @param file file to get data from
     * @return Map generated from the file
     * @throws FileNotFoundException if the file was not found or was not accessible
     * @throws IOException if an I/O occurs
     */
    public static Map loadMapFromFile(File file) throws IOException {
        Pair<FileParser, Boolean> parser= getFileParser(file);
        return parser.getKey().getLevel(file, parser.getValue());
    }

    /**
     * Save a file in a specific format, this format is defined by the file extension
     * This file extention could be: ".level", ".slevel", ".serialized", ".sserialized"
     * for save file use the .s variations
     * @param file file name to be saved to with the right extension
     * @param map map file to save
     * @throws NotSerializableException the file extension is not recognised
     * @throws FileNotFoundException The file could not be created
     * @throws IOException if an I/O occurs
     */
    public static void saveFileFromMap(File file, Map map) throws IOException {
        Pair<FileParser, Boolean> parser= getFileParser(file);
        parser.getKey().saveLevel(file, map, parser.getValue());
    }

    private static Pair<FileParser, Boolean> getFileParser(File file) throws NotSerializableException {
        FileParser fileParser;
        boolean save_data;

        if (file.toString().toLowerCase().endsWith(".level")){
            fileParser = new BinaryParser();
            save_data = false;
        }else if(file.toString().toLowerCase().endsWith(".slevel")){
            fileParser = new BinaryParser();
            save_data = true;
        }else if(file.toString().toLowerCase().endsWith(".serialized")){
            fileParser = new SerializeParser();
            save_data = false;
        }else if(file.toString().toLowerCase().endsWith(".sserialized")) {
            fileParser = new SerializeParser();
            save_data = true;
        }else {
            throw new NotSerializableException("This file format is not supported");
        }
        return new Pair<FileParser, Boolean>(fileParser, save_data);
    }

    public static void main(String[] args) throws IOException {
        Scanner in = new Scanner(System.in);
        Map level = new Map();

        System.out.print("Entrez le nom du fichier:");
        File file = new File(in.nextLine());

        System.out.print("Entrez la largeur de la map:");
        int map_width = in.nextInt();

        System.out.print("Entrez la hauteur de la map:");
        int map_height = in.nextInt();

        boolean[][] map_shape = new boolean[map_height][map_width];

        for (int i = 0; i < map_height; i++) {
            for (int j = 0; j < map_width; j++) {
                System.out.print("mur (" + i + ", " + j + ")? (y/n):");
                map_shape[i][j] = in.next(".").charAt(0) != 'y';
            }
        }

        level.setShape(map_shape);
        System.out.println(level);
        System.out.print("Entrez le nombre de pieces:");
        int piece_amount = in.nextInt();

        for (int i = 0; i < piece_amount; i++) {
            System.out.print("Entrez la largeur de la piece" + (i+1) +": ");
            int _piece_width = in.nextInt();

            System.out.print("Entrez la hauteur de la piece" + (i+1) +": ");
            int _piece_height = in.nextInt();
            boolean[][] _piece_shape = new boolean[_piece_height][_piece_width];

            for (int k = 0; k < _piece_height; k++) {
                for (int j = 0; j < _piece_width; j++) {
                    System.out.print("mur (" + k + ", " + j + ")? (y/n):");
                    _piece_shape[k][j] = in.next(".").charAt(0) != 'y';
                }
            }

            level.addPiece(new Piece(_piece_shape));
        }
        saveFileFromMap(file, level);
    }
}