package geometry

import (
	"github.com/go-gl/gl/v4.6-core/gl"
	"github.com/udhos/gwob"
)

// attributes:
// position 3 * float
// texture  2 * float
// normal   3 * float

type Geometry struct {
	vao  uint32
	vbo  uint32
	ebo  uint32
	size int32
}

func (g Geometry) Draw() {
	gl.BindVertexArray(g.vao)
	gl.BindBuffer(gl.ARRAY_BUFFER, g.vbo)
	gl.DrawElementsWithOffset(gl.TRIANGLES, g.size, gl.UNSIGNED_INT, 0)
}

func (g Geometry) Delete() {
	gl.DeleteVertexArrays(1, &g.vao)
	gl.DeleteBuffers(1, &g.ebo)
	gl.DeleteBuffers(1, &g.vbo)
}

func new(coords []float32, indicies []int) (Geometry, error) {
	var geometry Geometry

	unsignedIndicies := make([]uint32, len(indicies))
	for i, v := range indicies {
		unsignedIndicies[i] = uint32(v)
	}

	// vao
	gl.GenVertexArrays(1, &geometry.vao)
	gl.BindVertexArray(geometry.vao)

	// vbo
	gl.GenBuffers(1, &geometry.vbo)
	gl.BindBuffer(gl.ARRAY_BUFFER, geometry.vbo)
	gl.BufferData(gl.ARRAY_BUFFER, len(coords)*4, gl.Ptr(coords), gl.STATIC_DRAW)

	// attributes
	// position
	gl.VertexAttribPointerWithOffset(0, 3, gl.FLOAT, false, 8*4, 0)
	gl.EnableVertexAttribArray(0)

	// texture
	gl.VertexAttribPointerWithOffset(1, 2, gl.FLOAT, false, 8*4, 3*4)
	gl.EnableVertexAttribArray(1)

	// normal
	gl.VertexAttribPointerWithOffset(2, 3, gl.FLOAT, false, 8*4, 5*4)
	gl.EnableVertexAttribArray(2)

	// ebo
	gl.GenBuffers(1, &geometry.ebo)
	gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, geometry.ebo)
	gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(unsignedIndicies)*4, gl.Ptr(unsignedIndicies), gl.STATIC_DRAW)
	geometry.size = int32(len(indicies))

	return geometry, nil
}

func LoadOBJ(path string) (geometries Geometry, err error) {
	o, err := gwob.NewObjFromFile(path, &gwob.ObjParserOptions{})
	if err != nil {
		return geometries, err
	}

	return new(o.Coord, o.Indices)
}
