package core.engine;

import core.engine.model.RawModel;
import utils.vectors.Vector2f;
import utils.vectors.Vector3f;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

public class OBJLoader {

    public static RawModel loadOBJModel(String fileName, Loader loader) {
        FileReader fileReader = null;
        try {
            fileReader = new FileReader("res/" + fileName + ".obj");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        if(fileReader != null) {
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line = null;
            List<Vector3f> vertices = new ArrayList<>();
            List<Vector2f> textures = new ArrayList<>();
            List<Vector3f> normals = new ArrayList<>();
            List<Integer> indices = new ArrayList<>();

            float[] verticesArray = null;
            float[] normalsArray = null;
            float[] texturesArray = null;
            int[] indicesArray = null;

            try {
                while(bufferedReader.ready()) {
                    line = bufferedReader.readLine();
                    String[] splittedLine = line.split(" ");
                    if(splittedLine[0].equals("v")) {
                        Vector3f vertex = new Vector3f(Float.parseFloat(splittedLine[1]),
                                Float.parseFloat(splittedLine[2]), Float.parseFloat(splittedLine[3]));
                        vertices.add(vertex);
                    } else if(splittedLine[0].equals("vt")) {
                        Vector2f texture = new Vector2f(Float.parseFloat(splittedLine[1]), Float.parseFloat(splittedLine[2]));
                        textures.add(texture);
                    } else if(splittedLine[0].equals("vn")) {
                        Vector3f normal = new Vector3f(Float.parseFloat(splittedLine[1]),
                                Float.parseFloat(splittedLine[2]), Float.parseFloat(splittedLine[3]));
                        normals.add(normal);
                    } else if(splittedLine[0].equals("f")) {
                        //No more vertices/textures/normals should be added at this point in the file
                        texturesArray = new float[vertices.size()*2];
                        normalsArray = new float[vertices.size()*3];
                        break;
                    }
                }

                while(line != null) {
                    if(!line.startsWith("f ")) {
                        line = bufferedReader.readLine();
                        continue;
                    }

                    String[] splittedLine = line.split(" ");
                    String[] vertex1 = splittedLine[1].split("/");
                    String[] vertex2 = splittedLine[2].split("/");
                    String[] vertex3 = splittedLine[3].split("/");

                    processVertex(vertex1, indices, textures, normals, texturesArray, normalsArray);
                    processVertex(vertex2, indices, textures, normals, texturesArray, normalsArray);
                    processVertex(vertex3, indices, textures, normals, texturesArray, normalsArray);

                    line = bufferedReader.readLine();
                }

                bufferedReader.close();
                fileReader.close();
            } catch(Exception e) {
                e.printStackTrace();
            }

            verticesArray = new float[vertices.size()*3];
            indicesArray = new int[indices.size()];
            int vertexPointer = 0;

            for(Vector3f vertex: vertices) {
                verticesArray[vertexPointer++] = vertex.x;
                verticesArray[vertexPointer++] = vertex.y;
                verticesArray[vertexPointer++] = vertex.z;
            }

            for(int i=0; i<indices.size(); i++) {
                indicesArray[i] = indices.get(i);
            }

            return loader.loadToVAO(verticesArray, texturesArray, normalsArray, indicesArray);
        } else {
            return null;
        }
    }

    private static void processVertex(String[] vertexData, List<Integer> indices, List<Vector2f> textures,
                                      List<Vector3f> normals, float[] textureArray, float[] normalsArray) {
        int currentVertexPointer = Integer.parseInt(vertexData[0]) -1;
        indices.add(currentVertexPointer);
        Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1])-1);
        textureArray[currentVertexPointer*2] = currentTex.x;
        textureArray[currentVertexPointer*2+1] = 1 - currentTex.y;
        Vector3f currentNorm = normals.get(Integer.parseInt(vertexData[2])-1);
        normalsArray[currentVertexPointer*3] = currentNorm.x;
        normalsArray[currentVertexPointer*3+1] = currentNorm.y;
        normalsArray[currentVertexPointer*3+2] = currentNorm.z;

    }



}
