package surface

import (
	"fmt"
	"unsafe"

	"github.com/go-gl/gl/v4.1-core/gl"
)

var vertices = []float32{
	// Position Texcoords
	-1.0, +1.0, 0.0, 0.0, // Top-left
	-1.0, -1.0, 0.0, 1.0, // Bottom-left
	+1.0, -1.0, 1.0, 1.0, // Bottom-right
	+1.0, +1.0, 1.0, 0.0, // Top-right
}

var indices = []uint32{
	0, 1, 2,
	0, 2, 3,
}

func loadShader(t uint32, source string) (uint32, error) {
	// Create
	shader := gl.CreateShader(t)

	// Load source
	sources, free := gl.Strs(source)
	gl.ShaderSource(shader, 1, sources, nil)
	free()

	// Compile
	gl.CompileShader(shader)

	// Check status
	var status int32
	gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
	if status == 0 {
		// Error
		buf := make([]byte, 5*1024)
		var length int32
		gl.GetShaderInfoLog(shader, int32(len(buf)), &length, (*uint8)(unsafe.Pointer(&buf[0])))
		if length > 0 {
			length--
		}
		gl.DeleteShader(shader)
		//maxVersion := gl.GoStr(gl.GetString(gl.SHADING_LANGUAGE_VERSION))
		return 0, fmt.Errorf("failed to compile shader\n%s", string(buf[0:int(length)]))
	}

	return shader, nil
}

func loadProgram(vertexSource, fragmentSource string) (uint32, error) {
	// Vertex shader
	vertexShader, err := loadShader(gl.VERTEX_SHADER, vertexSource)
	if err != nil {
		return 0, err
	}
	// Fragment shader
	fragmentShader, err := loadShader(gl.FRAGMENT_SHADER, fragmentSource)
	if err != nil {
		return 0, err
	}
	// Shader program
	shaderProgram := gl.CreateProgram()
	gl.AttachShader(shaderProgram, vertexShader)
	gl.AttachShader(shaderProgram, fragmentShader)
	gl.LinkProgram(shaderProgram)

	var status int32
	gl.GetProgramiv(shaderProgram, gl.LINK_STATUS, &status)
	if status == 0 {
		// Error
		buf := make([]byte, 5*1024)
		var length int32
		gl.GetProgramInfoLog(shaderProgram, int32(len(buf)), &length, (*uint8)(unsafe.Pointer(&buf[0])))
		if length > 0 {
			length--
		}
		gl.DeleteProgram(shaderProgram)
		//maxVersion := gl.GoStr(gl.GetString(gl.SHADING_LANGUAGE_VERSION))
		return 0, fmt.Errorf("Failed to link program\n%s", string(buf[0:int(length)]))
	}

	// Clean no longer needed shaders
	gl.DeleteShader(vertexShader)
	gl.DeleteShader(fragmentShader)

	return shaderProgram, nil
}
