package io;

import Jama.Matrix;
import geometric.Triangle;

import java.io.*;
import java.util.*;

import util.Model;


import java.net.URL;
import java.net.URLClassLoader;

/**
 * This class provides static methods for reading and writing meshes from .off-files.
 * 
 * 
 */
public class ModelIO {

	/**
	 * Reads the mesh from the .off-file given by the path and returns it as a {@link Model}.
	 * 
	 * @param path
	 * @return
	 */
	public static Model loadModel(File path) {
		try {
			int numberOfVertices, numberOfTriangles;

			BufferedReader in = new BufferedReader(new FileReader(path));
			String s = in.readLine();
			if (!s.equals("OFF")) {
				throw new CorruptOFFFileException("Illegal File Header");
			}
			s = in.readLine();
			StringTokenizer tokenizer = new StringTokenizer(s);
			numberOfVertices = Integer.parseInt(tokenizer.nextToken());
			numberOfTriangles = Integer.parseInt(tokenizer.nextToken());

			if (numberOfTriangles < 1 || numberOfVertices < 3) {
				throw new CorruptOFFFileException("Invalid geometry declared");
			}
			
			ArrayList<Matrix> vertices = new ArrayList<Matrix>(numberOfVertices);
			Triangle[] triangles = new Triangle[numberOfTriangles];

			NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
			
			for (int i = 0; i < numberOfVertices; i++) {
				s = in.readLine();
				
				double[] ps = new double[3];
				tokenizer = new StringTokenizer(s);
				for (int j = 0; j < 3; j++) {
					Number number = format.parse("1,234");
					ps[j] = Double.parseDouble(tokenizer.nextToken());
				}
        
				vertices.add(new Matrix(ps, 3));
			}
			
			for (int i = 0; i < numberOfTriangles; i++) {
				s = in.readLine();
				tokenizer = new StringTokenizer(s);
				
				if ( Integer.parseInt(tokenizer.nextToken()) != 3)
				{
					System.out.println("illegal face ");
					throw new CorruptOFFFileException("Illegal Face declared");
				}

				int[] v = new int[3];
				for (int j = 0; j < 3; j++) {
					v[j] = Integer.parseInt(tokenizer.nextToken());
				}
				triangles[i] = new Triangle(v[0], v[1], v[2], vertices);
			}

			in.close();
			return new Model(vertices, triangles);
		} catch (FileNotFoundException e) {
			System.out.println("File not found: " + path.getAbsolutePath());
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Writes the given {@link Model} to the given path as .off-file
	 * 
	 * @param path
	 * @param model
	 */

	public static void writeModelToOFF(File path, Model model) {
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(path));
			out.write("OFF");
			out.newLine();

			ArrayList<Matrix> vertices = model.getVertices();
			Triangle[] triangles = model.getTriangles();

			out.write(vertices.size() + " " + triangles.length + " " + "0");
			out.newLine();

			for (int i = 0; i < vertices.size(); i++) {
				for (int j = 0; j < 3; j++) {
					out.write(vertices.get(i).get(j, 0) + " ");
				}
				out.newLine();
			}

			for (Triangle element : triangles) {
				out.write("3 " + element.getP0() + " " + element.getP1() + " " + element.getP2());
				out.newLine();
			}

			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
