// Copyright 2015 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.

package gldriver

import (
	"image"
	"image/color"
	"image/draw"
	"sync"

	"golang.org/x/exp/shiny/driver/internal/drawer"
	"golang.org/x/exp/shiny/driver/internal/event"
	"golang.org/x/exp/shiny/driver/internal/lifecycler"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/image/math/f64"
	"golang.org/x/mobile/event/lifecycle"
	"golang.org/x/mobile/event/size"
	"golang.org/x/mobile/gl"
)

type windowImpl struct {
	s *screenImpl

	// id is an OS-specific data structure for the window.
	//	- Cocoa:   ScreenGLView*
	//	- X11:     Window
	//	- Windows: win32.HWND
	id uintptr

	// ctx is a C data structure for the GL context.
	//	- Cocoa:   uintptr holding a NSOpenGLContext*.
	//	- X11:     uintptr holding an EGLSurface.
	//	- Windows: ctxWin32
	ctx interface{}

	lifecycler lifecycler.State
	// TODO: Delete the field below (and the useLifecycler constant), and use
	// the field above for cocoa and win32.
	lifecycleStage lifecycle.Stage // current stage

	event.Deque
	publish     chan struct{}
	publishDone chan screen.PublishResult
	drawDone    chan struct{}

	// glctxMu is a mutex that enforces the atomicity of methods like
	// Texture.Upload or Window.Draw that are conceptually one operation
	// but are implemented by multiple OpenGL calls. OpenGL is a stateful
	// API, so interleaving OpenGL calls from separate higher-level
	// operations causes inconsistencies.
	glctxMu sync.Mutex
	glctx   gl.Context
	worker  gl.Worker
	// backBufferBound is whether the default Framebuffer, with ID 0, also
	// known as the back buffer or the window's Framebuffer, is bound and its
	// viewport is known to equal the window size. It can become false when we
	// bind to a texture's Framebuffer or when the window size changes.
	backBufferBound bool

	// szMu protects only sz. If you need to hold both glctxMu and szMu, the
	// lock ordering is to lock glctxMu first (and unlock it last).
	szMu sync.Mutex
	sz   size.Event
}

// NextEvent implements the screen.EventDeque interface.
func (w *windowImpl) NextEvent() interface{} {
	e := w.Deque.NextEvent()
	if handleSizeEventsAtChannelReceive {
		if sz, ok := e.(size.Event); ok {
			w.glctxMu.Lock()
			w.backBufferBound = false
			w.szMu.Lock()
			w.sz = sz
			w.szMu.Unlock()
			w.glctxMu.Unlock()
		}
	}
	return e
}

func (w *windowImpl) Release() {
	// There are two ways a window can be closed: the Operating System or
	// Desktop Environment can initiate (e.g. in response to a user clicking a
	// red button), or the Go app can programatically close the window (by
	// calling Window.Release).
	//
	// When the OS closes a window:
	//	- Cocoa:   Obj-C's windowWillClose calls Go's windowClosing.
	//	- X11:     the X11 server sends a WM_DELETE_WINDOW message.
	//	- Windows: TODO: implement and document this.
	//
	// This should send a lifecycle event (To: StageDead) to the Go app's event
	// loop, which should respond by calling Window.Release (this method).
	// Window.Release is where system resources are actually cleaned up.
	//
	// When Window.Release is called, the closeWindow call below:
	//	- Cocoa:   calls Obj-C's performClose, which emulates the red button
	//	           being clicked. (TODO: document how this actually cleans up
	//	           resources??)
	//	- X11:     calls C's XDestroyWindow.
	//	- Windows: TODO: implement and document this.
	//
	// On Cocoa, if these two approaches race, experiments suggest that the
	// race is won by performClose (which is called serially on the main
	// thread). Even if that isn't true, the windowWillClose handler is
	// idempotent.

	theScreen.mu.Lock()
	delete(theScreen.windows, w.id)
	theScreen.mu.Unlock()

	closeWindow(w.id)
}

func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) {
	originalSRMin := sr.Min
	sr = sr.Intersect(src.Bounds())
	if sr.Empty() {
		return
	}
	dp = dp.Add(sr.Min.Sub(originalSRMin))
	// TODO: keep a texture around for this purpose?
	t, err := w.s.NewTexture(sr.Size())
	if err != nil {
		panic(err)
	}
	t.Upload(image.Point{}, src, sr)
	w.Draw(f64.Aff3{
		1, 0, float64(dp.X),
		0, 1, float64(dp.Y),
	}, t, t.Bounds(), draw.Src, nil)
	t.Release()
}

func useOp(glctx gl.Context, op draw.Op) {
	if op == draw.Over {
		glctx.Enable(gl.BLEND)
		glctx.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
	} else {
		glctx.Disable(gl.BLEND)
	}
}

func (w *windowImpl) bindBackBuffer() {
	w.szMu.Lock()
	sz := w.sz
	w.szMu.Unlock()

	w.backBufferBound = true
	w.glctx.BindFramebuffer(gl.FRAMEBUFFER, gl.Framebuffer{Value: 0})
	w.glctx.Viewport(0, 0, sz.WidthPx, sz.HeightPx)
}

func (w *windowImpl) fill(mvp f64.Aff3, src color.Color, op draw.Op) {
	w.glctxMu.Lock()
	defer w.glctxMu.Unlock()

	if !w.backBufferBound {
		w.bindBackBuffer()
	}

	doFill(w.s, w.glctx, mvp, src, op)
}

func doFill(s *screenImpl, glctx gl.Context, mvp f64.Aff3, src color.Color, op draw.Op) {
	useOp(glctx, op)
	if !glctx.IsProgram(s.fill.program) {
		p, err := compileProgram(glctx, fillVertexSrc, fillFragmentSrc)
		if err != nil {
			// TODO: initialize this somewhere else we can better handle the error.
			panic(err.Error())
		}
		s.fill.program = p
		s.fill.pos = glctx.GetAttribLocation(p, "pos")
		s.fill.mvp = glctx.GetUniformLocation(p, "mvp")
		s.fill.color = glctx.GetUniformLocation(p, "color")
		s.fill.quad = glctx.CreateBuffer()

		glctx.BindBuffer(gl.ARRAY_BUFFER, s.fill.quad)
		glctx.BufferData(gl.ARRAY_BUFFER, quadCoords, gl.STATIC_DRAW)
	}
	glctx.UseProgram(s.fill.program)

	writeAff3(glctx, s.fill.mvp, mvp)

	r, g, b, a := src.RGBA()
	glctx.Uniform4f(
		s.fill.color,
		float32(r)/65535,
		float32(g)/65535,
		float32(b)/65535,
		float32(a)/65535,
	)

	glctx.BindBuffer(gl.ARRAY_BUFFER, s.fill.quad)
	glctx.EnableVertexAttribArray(s.fill.pos)
	glctx.VertexAttribPointer(s.fill.pos, 2, gl.FLOAT, false, 0, 0)

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

	glctx.DisableVertexAttribArray(s.fill.pos)
}

func (w *windowImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) {
	minX := float64(dr.Min.X)
	minY := float64(dr.Min.Y)
	maxX := float64(dr.Max.X)
	maxY := float64(dr.Max.Y)
	w.fill(w.mvp(
		minX, minY,
		maxX, minY,
		minX, maxY,
	), src, op)
}

func (w *windowImpl) DrawUniform(src2dst f64.Aff3, src color.Color, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	minX := float64(sr.Min.X)
	minY := float64(sr.Min.Y)
	maxX := float64(sr.Max.X)
	maxY := float64(sr.Max.Y)
	w.fill(w.mvp(
		src2dst[0]*minX+src2dst[1]*minY+src2dst[2],
		src2dst[3]*minX+src2dst[4]*minY+src2dst[5],
		src2dst[0]*maxX+src2dst[1]*minY+src2dst[2],
		src2dst[3]*maxX+src2dst[4]*minY+src2dst[5],
		src2dst[0]*minX+src2dst[1]*maxY+src2dst[2],
		src2dst[3]*minX+src2dst[4]*maxY+src2dst[5],
	), src, op)
}

func (w *windowImpl) Draw(src2dst f64.Aff3, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	t := src.(*textureImpl)
	sr = sr.Intersect(t.Bounds())
	if sr.Empty() {
		return
	}

	w.glctxMu.Lock()
	defer w.glctxMu.Unlock()

	if !w.backBufferBound {
		w.bindBackBuffer()
	}

	useOp(w.glctx, op)
	w.glctx.UseProgram(w.s.texture.program)

	// Start with src-space left, top, right and bottom.
	srcL := float64(sr.Min.X)
	srcT := float64(sr.Min.Y)
	srcR := float64(sr.Max.X)
	srcB := float64(sr.Max.Y)
	// Transform to dst-space via the src2dst matrix, then to a MVP matrix.
	writeAff3(w.glctx, w.s.texture.mvp, w.mvp(
		src2dst[0]*srcL+src2dst[1]*srcT+src2dst[2],
		src2dst[3]*srcL+src2dst[4]*srcT+src2dst[5],
		src2dst[0]*srcR+src2dst[1]*srcT+src2dst[2],
		src2dst[3]*srcR+src2dst[4]*srcT+src2dst[5],
		src2dst[0]*srcL+src2dst[1]*srcB+src2dst[2],
		src2dst[3]*srcL+src2dst[4]*srcB+src2dst[5],
	))

	// OpenGL's fragment shaders' UV coordinates run from (0,0)-(1,1),
	// unlike vertex shaders' XY coordinates running from (-1,+1)-(+1,-1).
	//
	// We are drawing a rectangle PQRS, defined by two of its
	// corners, onto the entire texture. The two quads may actually
	// be equal, but in the general case, PQRS can be smaller.
	//
	//	(0,0) +---------------+ (1,0)
	//	      |  P +-----+ Q  |
	//	      |    |     |    |
	//	      |  S +-----+ R  |
	//	(0,1) +---------------+ (1,1)
	//
	// The PQRS quad is always axis-aligned. First of all, convert
	// from pixel space to texture space.
	tw := float64(t.size.X)
	th := float64(t.size.Y)
	px := float64(sr.Min.X-0) / tw
	py := float64(sr.Min.Y-0) / th
	qx := float64(sr.Max.X-0) / tw
	sy := float64(sr.Max.Y-0) / th
	// 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
	writeAff3(w.glctx, w.s.texture.uvp, f64.Aff3{
		qx - px, 0, px,
		0, sy - py, py,
	})

	w.glctx.ActiveTexture(gl.TEXTURE0)
	w.glctx.BindTexture(gl.TEXTURE_2D, t.id)
	w.glctx.Uniform1i(w.s.texture.sample, 0)

	w.glctx.BindBuffer(gl.ARRAY_BUFFER, w.s.texture.quad)
	w.glctx.EnableVertexAttribArray(w.s.texture.pos)
	w.glctx.VertexAttribPointer(w.s.texture.pos, 2, gl.FLOAT, false, 0, 0)

	w.glctx.BindBuffer(gl.ARRAY_BUFFER, w.s.texture.quad)
	w.glctx.EnableVertexAttribArray(w.s.texture.inUV)
	w.glctx.VertexAttribPointer(w.s.texture.inUV, 2, gl.FLOAT, false, 0, 0)

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

	w.glctx.DisableVertexAttribArray(w.s.texture.pos)
	w.glctx.DisableVertexAttribArray(w.s.texture.inUV)
}

func (w *windowImpl) Copy(dp image.Point, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	drawer.Copy(w, dp, src, sr, op, opts)
}

func (w *windowImpl) Scale(dr image.Rectangle, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	drawer.Scale(w, dr, src, sr, op, opts)
}

func (w *windowImpl) mvp(tlx, tly, trx, try, blx, bly float64) f64.Aff3 {
	w.szMu.Lock()
	sz := w.sz
	w.szMu.Unlock()

	return calcMVP(sz.WidthPx, sz.HeightPx, tlx, tly, trx, try, blx, bly)
}

// calcMVP returns the Model View Projection matrix that maps the quadCoords
// unit square, (0, 0) to (1, 1), to a quad QV, such that QV in vertex shader
// space corresponds to the quad QP in pixel space, where QP is defined by
// three of its four corners - the arguments to this function. The three
// corners are nominally the top-left, top-right and bottom-left, but there is
// no constraint that e.g. tlx < trx.
//
// In pixel space, the window ranges from (0, 0) to (widthPx, heightPx). The
// Y-axis points downwards.
//
// In vertex shader space, the window ranges from (-1, +1) to (+1, -1), which
// is a 2-unit by 2-unit square. The Y-axis points upwards.
func calcMVP(widthPx, heightPx int, tlx, tly, trx, try, blx, bly float64) f64.Aff3 {
	// Convert from pixel coords to vertex shader coords.
	invHalfWidth := +2 / float64(widthPx)
	invHalfHeight := -2 / float64(heightPx)
	tlx = tlx*invHalfWidth - 1
	tly = tly*invHalfHeight + 1
	trx = trx*invHalfWidth - 1
	try = try*invHalfHeight + 1
	blx = blx*invHalfWidth - 1
	bly = bly*invHalfHeight + 1

	// The resultant affine matrix:
	//	- maps (0, 0) to (tlx, tly).
	//	- maps (1, 0) to (trx, try).
	//	- maps (0, 1) to (blx, bly).
	return f64.Aff3{
		trx - tlx, blx - tlx, tlx,
		try - tly, bly - tly, tly,
	}
}

func (w *windowImpl) Publish() screen.PublishResult {
	// gl.Flush is a lightweight (on modern GL drivers) blocking call
	// that ensures all GL functions pending in the gl package have
	// been passed onto the GL driver before the app package attempts
	// to swap the screen buffer.
	//
	// This enforces that the final receive (for this paint cycle) on
	// gl.WorkAvailable happens before the send on publish.
	w.glctxMu.Lock()
	w.glctx.Flush()
	w.glctxMu.Unlock()

	w.publish <- struct{}{}
	res := <-w.publishDone

	select {
	case w.drawDone <- struct{}{}:
	default:
	}

	return res
}
