use super::{Point3, Vec3};
use std::fs::File;
use std::io::{self, prelude::*, BufReader};

pub struct Face {
    aNormal: Vec3,
    bNormal: Vec3,
    cNormal: Vec3,
    aTexture: Point3,
    bTexture: Point3,
    cTexture: Point3,
    a: Point3,
    b: Point3,
    c: Point3,
    onlyPoints: boolean,
}

pub struct Obj  {
    vertexes: Vec<Point3>,
    textures: Vec<Point3>,
    normals: Vec<Vec3>,
    faces: Vec<Face>,
}

impl Obj {
    pub fn fromFile(&self, path: String) -> Self {
        let file = File::open(path)?;
        let reader = BufReader::new(file);

        for line in reader.lines() {
            let split = line.split_whitespace();

            match split[0] {
                // vertexes
                "v" => {
                    if split.len() != 4 { continue };
                    self.vertexes.push(Point3::new(
                        split[1].parse::<f64>(),
                        split[2].parse::<f64>(),
                        split[3].parse::<f64>()
                    ));
                    // can throw ParseFloatError
                },
                // textures
                "vt" => {
                    if split.len() < 2 { continue };
                    normals.push(Point3::new(
                        split[1].parse::<f64>(),
                        if split.len() >= 3 { split[2].parse::<f64>() } else { 0.0 },
                        if split.len() >= 4 { split[3].parse::<f64>() } else { 0.0 },
                    ));
                    // can throw ParseFloatError
                },
                // normals
                "vn" => {
                    if split.len() != 4 { continue };
                    normals.push(Vec3::new(
                        split[1].parse::<f64>(),
                        split[2].parse::<f64>(),
                        split[3].parse::<f64>()
                    ));
                    // can throw ParseFloatError
                },
                // faces
                "f" => {
                    if split.len() != 4 { continue };

                    if split[1].contains("/") { // format 'f 1/4/6 2/7/8 3/7/8'
                        let a = split[1].split("/");
                        let b = split[2].split("/");
                        let c = split[3].split("/");
                        faces.push(
                            Face {
                                aNormal: if a[1] != "" { normals[a[1].parse::<u64>()] } else { Vec3::empty() },
                                bNormal: if b[1] != "" { normals[b[1].parse::<u64>()] } else { Vec3::empty() },
                                cNormal: if c[1] != "" { normals[c[1].parse::<u64>()] } else { Vec3::empty() },
                                aTexture: if a[2] != "" { textures[a[1].parse::<u64>()] } else { Point3::empty() }
                            }
                        )
                    } else { // format 'f 1 2 3'
                        faces.push(Point3::new(
                            split[1].parse::<f64>(),
                            split[2].parse::<f64>(),
                            split[3].parse::<f64>()
                        ));
                    }
                    
                    // can throw ParseFloatError
                }
            }
        }

        Ok(())
    }
}