// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build linux || darwin || windows
// +build linux darwin windows

package glutil

import (
	"encoding/binary"
	"image"
	"runtime"
	"sync"

	"golang.org/x/mobile/event/size"
	"golang.org/x/mobile/exp/f32"
	"golang.org/x/mobile/geom"
	"golang.org/x/mobile/gl"
)

// Images maintains the shared state used by a set of *Image objects.
type Images struct {
	glctx         gl.Context
	quadXY        gl.Buffer
	quadUV        gl.Buffer
	program       gl.Program
	pos           gl.Attrib
	mvp           gl.Uniform
	uvp           gl.Uniform
	inUV          gl.Attrib
	textureSample gl.Uniform

	mu           sync.Mutex
	activeImages int
}

// NewImages creates an *Images.
func NewImages(glctx gl.Context) *Images {
	program, err := CreateProgram(glctx, vertexShader, fragmentShader)
	if err != nil {
		panic(err)
	}

	p := &Images{
		glctx:         glctx,
		quadXY:        glctx.CreateBuffer(),
		quadUV:        glctx.CreateBuffer(),
		program:       program,
		pos:           glctx.GetAttribLocation(program, "pos"),
		mvp:           glctx.GetUniformLocation(program, "mvp"),
		uvp:           glctx.GetUniformLocation(program, "uvp"),
		inUV:          glctx.GetAttribLocation(program, "inUV"),
		textureSample: glctx.GetUniformLocation(program, "textureSample"),
	}

	glctx.BindBuffer(gl.ARRAY_BUFFER, p.quadXY)
	glctx.BufferData(gl.ARRAY_BUFFER, quadXYCoords, gl.STATIC_DRAW)
	glctx.BindBuffer(gl.ARRAY_BUFFER, p.quadUV)
	glctx.BufferData(gl.ARRAY_BUFFER, quadUVCoords, gl.STATIC_DRAW)

	return p
}

// Release releases any held OpenGL resources.
// All *Image objects must be released first, or this function panics.
func (p *Images) Release() {
	if p.program == (gl.Program{}) {
		return
	}

	p.mu.Lock()
	rem := p.activeImages
	p.mu.Unlock()
	if rem > 0 {
		panic("glutil.Images.Release called, but active *Image objects remain")
	}

	p.glctx.DeleteProgram(p.program)
	p.glctx.DeleteBuffer(p.quadXY)
	p.glctx.DeleteBuffer(p.quadUV)

	p.program = gl.Program{}
}

// Image bridges between an *image.RGBA and an OpenGL texture.
//
// The contents of the *image.RGBA can be uploaded as a texture and drawn as a
// 2D quad.
//
// The number of active Images must fit in the system's OpenGL texture limit.
// The typical use of an Image is as a texture atlas.
type Image struct {
	RGBA *image.RGBA

	gltex  gl.Texture
	width  int
	height int
	images *Images
}

// NewImage creates an Image of the given size.
//
// Both a host-memory *image.RGBA and a GL texture are created.
func (p *Images) NewImage(w, h int) *Image {
	dx := roundToPower2(w)
	dy := roundToPower2(h)

	// TODO(crawshaw): Using VertexAttribPointer we can pass texture
	// data with a stride, which would let us use the exact number of
	// pixels on the host instead of the rounded up power 2 size.
	m := image.NewRGBA(image.Rect(0, 0, dx, dy))

	img := &Image{
		RGBA:   m.SubImage(image.Rect(0, 0, w, h)).(*image.RGBA),
		images: p,
		width:  dx,
		height: dy,
	}

	p.mu.Lock()
	p.activeImages++
	p.mu.Unlock()

	img.gltex = p.glctx.CreateTexture()

	p.glctx.BindTexture(gl.TEXTURE_2D, img.gltex)
	p.glctx.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, img.width, img.height, gl.RGBA, gl.UNSIGNED_BYTE, nil)
	p.glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	p.glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	p.glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	p.glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)

	runtime.SetFinalizer(img, (*Image).Release)
	return img
}

func roundToPower2(x int) int {
	x2 := 1
	for x2 < x {
		x2 *= 2
	}
	return x2
}

// Upload copies the host image data to the GL device.
func (img *Image) Upload() {
	img.images.glctx.BindTexture(gl.TEXTURE_2D, img.gltex)
	img.images.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, img.width, img.height, gl.RGBA, gl.UNSIGNED_BYTE, img.RGBA.Pix)
}

// Release invalidates the Image and removes any underlying data structures.
// The Image cannot be used after being deleted.
func (img *Image) Release() {
	if img.gltex == (gl.Texture{}) {
		return
	}

	img.images.glctx.DeleteTexture(img.gltex)
	img.gltex = gl.Texture{}

	img.images.mu.Lock()
	img.images.activeImages--
	img.images.mu.Unlock()
}

// Draw draws the srcBounds part of the image onto a parallelogram, defined by
// three of its corners, in the current GL framebuffer.
func (img *Image) Draw(sz size.Event, topLeft, topRight, bottomLeft geom.Point, srcBounds image.Rectangle) {
	glimage := img.images
	glctx := img.images.glctx

	glctx.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
	glctx.Enable(gl.BLEND)

	// TODO(crawshaw): Adjust viewport for the top bar on android?
	glctx.UseProgram(glimage.program)
	{
		// We are drawing a parallelogram PQRS, defined by three of its
		// corners, onto the entire GL framebuffer ABCD. The two quads may
		// actually be equal, but in the general case, PQRS can be smaller,
		// and PQRS is not necessarily axis-aligned.
		//
		//	A +---------------+ B
		//	  |  P +-----+ Q  |
		//	  |    |     |    |
		//	  |  S +-----+ R  |
		//	D +---------------+ C
		//
		// There are two co-ordinate spaces: geom space and framebuffer space.
		// In geom space, the ABCD rectangle is:
		//
		//	(0, 0)           (geom.Width, 0)
		//	(0, geom.Height) (geom.Width, geom.Height)
		//
		// and the PQRS quad is:
		//
		//	(topLeft.X,    topLeft.Y)    (topRight.X, topRight.Y)
		//	(bottomLeft.X, bottomLeft.Y) (implicit,   implicit)
		//
		// In framebuffer space, the ABCD rectangle is:
		//
		//	(-1, +1) (+1, +1)
		//	(-1, -1) (+1, -1)
		//
		// First of all, convert from geom space to framebuffer space. For
		// later convenience, we divide everything by 2 here: px2 is half of
		// the P.X co-ordinate (in framebuffer space).
		px2 := -0.5 + float32(topLeft.X/sz.WidthPt)
		py2 := +0.5 - float32(topLeft.Y/sz.HeightPt)
		qx2 := -0.5 + float32(topRight.X/sz.WidthPt)
		qy2 := +0.5 - float32(topRight.Y/sz.HeightPt)
		sx2 := -0.5 + float32(bottomLeft.X/sz.WidthPt)
		sy2 := +0.5 - float32(bottomLeft.Y/sz.HeightPt)
		// Next, solve for the affine transformation matrix
		//	    [ a00 a01 a02 ]
		//	a = [ a10 a11 a12 ]
		//	    [   0   0   1 ]
		// that maps A to P:
		//	a × [ -1 +1 1 ]' = [ 2*px2 2*py2 1 ]'
		// and likewise maps B to Q and D to S. Solving those three constraints
		// implies that C maps to R, since affine transformations keep parallel
		// lines parallel. This gives 6 equations in 6 unknowns:
		//	-a00 + a01 + a02 = 2*px2
		//	-a10 + a11 + a12 = 2*py2
		//	+a00 + a01 + a02 = 2*qx2
		//	+a10 + a11 + a12 = 2*qy2
		//	-a00 - a01 + a02 = 2*sx2
		//	-a10 - a11 + a12 = 2*sy2
		// which gives:
		//	a00 = (2*qx2 - 2*px2) / 2 = qx2 - px2
		// and similarly for the other elements of a.
		writeAffine(glctx, glimage.mvp, &f32.Affine{{
			qx2 - px2,
			px2 - sx2,
			qx2 + sx2,
		}, {
			qy2 - py2,
			py2 - sy2,
			qy2 + sy2,
		}})
	}

	{
		// Mapping texture co-ordinates is similar, except that in texture
		// space, the ABCD rectangle is:
		//
		//	(0,0) (1,0)
		//	(0,1) (1,1)
		//
		// and the PQRS quad is always axis-aligned. First of all, convert
		// from pixel space to texture space.
		w := float32(img.width)
		h := float32(img.height)
		px := float32(srcBounds.Min.X-img.RGBA.Rect.Min.X) / w
		py := float32(srcBounds.Min.Y-img.RGBA.Rect.Min.Y) / h
		qx := float32(srcBounds.Max.X-img.RGBA.Rect.Min.X) / w
		sy := float32(srcBounds.Max.Y-img.RGBA.Rect.Min.Y) / h
		// Due to axis alignment, qy = py and sx = px.
		//
		// The simultaneous equations are:
		//	  0 +   0 + a02 = px
		//	  0 +   0 + a12 = py
		//	a00 +   0 + a02 = qx
		//	a10 +   0 + a12 = qy = py
		//	  0 + a01 + a02 = sx = px
		//	  0 + a11 + a12 = sy
		writeAffine(glctx, glimage.uvp, &f32.Affine{{
			qx - px,
			0,
			px,
		}, {
			0,
			sy - py,
			py,
		}})
	}

	glctx.ActiveTexture(gl.TEXTURE0)
	glctx.BindTexture(gl.TEXTURE_2D, img.gltex)
	glctx.Uniform1i(glimage.textureSample, 0)

	glctx.BindBuffer(gl.ARRAY_BUFFER, glimage.quadXY)
	glctx.EnableVertexAttribArray(glimage.pos)
	glctx.VertexAttribPointer(glimage.pos, 2, gl.FLOAT, false, 0, 0)

	glctx.BindBuffer(gl.ARRAY_BUFFER, glimage.quadUV)
	glctx.EnableVertexAttribArray(glimage.inUV)
	glctx.VertexAttribPointer(glimage.inUV, 2, gl.FLOAT, false, 0, 0)

	glctx.DrawArrays(gl.TRIANGLE_STRIP, 0, 4)

	glctx.DisableVertexAttribArray(glimage.pos)
	glctx.DisableVertexAttribArray(glimage.inUV)

	glctx.Disable(gl.BLEND)
}

var quadXYCoords = f32.Bytes(binary.LittleEndian,
	-1, +1, // top left
	+1, +1, // top right
	-1, -1, // bottom left
	+1, -1, // bottom right
)

var quadUVCoords = f32.Bytes(binary.LittleEndian,
	0, 0, // top left
	1, 0, // top right
	0, 1, // bottom left
	1, 1, // bottom right
)

const vertexShader = `#version 100
uniform mat3 mvp;
uniform mat3 uvp;
attribute vec3 pos;
attribute vec2 inUV;
varying vec2 UV;
void main() {
	vec3 p = pos;
	p.z = 1.0;
	gl_Position = vec4(mvp * p, 1);
	UV = (uvp * vec3(inUV, 1)).xy;
}
`

const fragmentShader = `#version 100
precision mediump float;
varying vec2 UV;
uniform sampler2D textureSample;
void main(){
	gl_FragColor = texture2D(textureSample, UV);
}
`
