import Foundation
import OrderedCollections


/*
extension ObjMaterial
{
	func convert() -> Material
	{
		var m = Material()
		m.diffuse = self.diffuse.setAlpha(self.alpha)
		if ![ .colour, .lambert, .shadowOnly ].contains(self.model)
		{
			m.specular = self.specular
			m.specularExp = self.specularExp
		}
		return m
	}
}
*/

public struct ObjLoader: LoaderProtocol
{
	public typealias T = Mesh

	public init() {}

	public func load(url: URL) -> T?
	{
		try? Self.read(url: url)
	}

	private static func read(url: URL) throws -> Mesh
	{
		return try read(model: try ObjReader.read(url: url))
	}

	public static func read(model: ObjModel) throws -> Mesh
	{
		var subMeshes: OrderedDictionary<String, Mesh.SubMesh> = .init()
		var vertices = [Mesh.Vertex]()
		var indices = [UInt16]()

		let readIndex =
		{ (v: ObjModel.Index) -> UInt16 in
			let vertex = Mesh.Vertex(
				position: model.positions[v.p],
				normal: model.normals[v.n],
				texCoord: model.texCoords[v.t])
			if let index = vertices.firstIndex(of: vertex)
			{
				indices.append(UInt16(index))
				return UInt16(index)
			}
			else
			{
				let index = UInt16(vertices.count)
				indices.append(index)
				vertices.append(vertex)
				return index
			}
		}

		for mesh in model.objects
		{
			let start = indices.count
			for face: ObjModel.Face in mesh.value.faces
			{
				switch face
				{
				case .triangle(let v1, let v2, let v3):
					for v in [ v1, v2, v3 ] { _ = readIndex(v) }
				case .quad(let v1, let v2, let v3, let v4):
					let n1 = readIndex(v1)
					_ = readIndex(v2)
					indices.append(readIndex(v3))
					_ = readIndex(v4)
					indices.append(n1)
				case .ngon(_): fallthrough
				default: break
				}
			}
			let length = indices.count - start
			if length > 0
			{
				subMeshes[mesh.key] = .init(start: start, length: length)
			}
		}

		return Mesh(vertices: vertices, indices: indices, subMeshes: subMeshes)
	}
}
