// 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 x11driver

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

	"github.com/jezek/xgb/render"
	"github.com/jezek/xgb/xproto"

	"golang.org/x/exp/shiny/screen"
	"golang.org/x/image/math/f64"
)

const textureDepth = 32

type textureImpl struct {
	s *screenImpl

	size image.Point
	xm   xproto.Pixmap
	xp   render.Picture

	// renderMu is a mutex that enforces the atomicity of methods like
	// Window.Draw that are conceptually one operation but are implemented by
	// multiple X11/Render calls. X11/Render is a stateful API, so interleaving
	// X11/Render calls from separate higher-level operations causes
	// inconsistencies.
	renderMu sync.Mutex

	releasedMu sync.Mutex
	released   bool
}

func (t *textureImpl) degenerate() bool        { return t.size.X == 0 || t.size.Y == 0 }
func (t *textureImpl) Size() image.Point       { return t.size }
func (t *textureImpl) Bounds() image.Rectangle { return image.Rectangle{Max: t.size} }

func (t *textureImpl) Release() {
	t.releasedMu.Lock()
	released := t.released
	t.released = true
	t.releasedMu.Unlock()

	if released || t.degenerate() {
		return
	}
	render.FreePicture(t.s.xc, t.xp)
	xproto.FreePixmap(t.s.xc, t.xm)
}

func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) {
	if t.degenerate() {
		return
	}
	src.(bufferUploader).upload(xproto.Drawable(t.xm), t.s.gcontext32, textureDepth, dp, sr)
}

func (t *textureImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) {
	if t.degenerate() {
		return
	}
	fill(t.s.xc, t.xp, dr, src, op)
}

// f64ToFixed converts from float64 to X11/Render's 16.16 fixed point.
func f64ToFixed(x float64) render.Fixed {
	return render.Fixed(x * 65536)
}

func inv(x *f64.Aff3) f64.Aff3 {
	invDet := 1 / (x[0]*x[4] - x[1]*x[3])
	return f64.Aff3{
		+x[4] * invDet,
		-x[1] * invDet,
		(x[1]*x[5] - x[2]*x[4]) * invDet,
		-x[3] * invDet,
		+x[0] * invDet,
		(x[2]*x[3] - x[0]*x[5]) * invDet,
	}
}

func (t *textureImpl) draw(xp render.Picture, src2dst *f64.Aff3, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) {
	sr = sr.Intersect(t.Bounds())
	if sr.Empty() {
		return
	}

	t.renderMu.Lock()
	defer t.renderMu.Unlock()

	// For simple copies and scales, the inverse matrix is trivial to compute,
	// and we do not need the "Src becomes OutReverse plus Over" dance (see
	// below). Thus, draw can be one render.SetPictureTransform call and then
	// one render.Composite call, regardless of whether or not op is Src.
	if src2dst[1] == 0 && src2dst[3] == 0 {
		dstXMin := float64(sr.Min.X)*src2dst[0] + src2dst[2]
		dstXMax := float64(sr.Max.X)*src2dst[0] + src2dst[2]
		if dstXMin > dstXMax {
			// TODO: check if this (and below) works when src2dst[0] < 0.
			dstXMin, dstXMax = dstXMax, dstXMin
		}
		dXMin := int(math.Floor(dstXMin))
		dXMax := int(math.Ceil(dstXMax))

		dstYMin := float64(sr.Min.Y)*src2dst[4] + src2dst[5]
		dstYMax := float64(sr.Max.Y)*src2dst[4] + src2dst[5]
		if dstYMin > dstYMax {
			// TODO: check if this (and below) works when src2dst[4] < 0.
			dstYMin, dstYMax = dstYMax, dstYMin
		}
		dYMin := int(math.Floor(dstYMin))
		dYMax := int(math.Ceil(dstYMax))

		render.SetPictureTransform(t.s.xc, t.xp, render.Transform{
			f64ToFixed(1 / src2dst[0]), 0, 0,
			0, f64ToFixed(1 / src2dst[4]), 0,
			0, 0, 1 << 16,
		})
		render.Composite(t.s.xc, renderOp(op), t.xp, 0, xp,
			int16(sr.Min.X), int16(sr.Min.Y), // SrcX, SrcY,
			0, 0, // MaskX, MaskY,
			int16(dXMin), int16(dYMin), // DstX, DstY,
			uint16(dXMax-dXMin), uint16(dYMax-dYMin), // Width, Height,
		)
		return
	}

	// The X11/Render transform matrix maps from destination pixels to source
	// pixels, so we invert src2dst.
	dst2src := inv(src2dst)
	render.SetPictureTransform(t.s.xc, t.xp, render.Transform{
		f64ToFixed(dst2src[0]), f64ToFixed(dst2src[1]), render.Fixed(sr.Min.X << 16),
		f64ToFixed(dst2src[3]), f64ToFixed(dst2src[4]), render.Fixed(sr.Min.Y << 16),
		0, 0, 1 << 16,
	})

	points := trifanPoints(src2dst, sr)
	if op == draw.Src {
		// render.TriFan visits every dst-space pixel in the axis-aligned
		// bounding box (AABB) containing the transformation of the sr
		// rectangle in src-space to a quad in dst-space.
		//
		// render.TriFan is like render.Composite, except that the AABB is
		// defined implicitly by the transformed triangle vertices instead of
		// being passed explicitly as arguments. It implies the minimal AABB.
		//
		// In any case, for arbitrary src2dst affine transformations, which
		// include rotations, this means that a naive render.TriFan call will
		// affect those pixels inside the AABB but outside the quad. For the
		// draw.Src operator, this means that pixels in that AABB can be
		// incorrectly set to zero.
		//
		// Instead, we implement the draw.Src operator as two render.TriFan
		// calls. The first one (using the PictOpOutReverse operator and a
		// fully opaque source) clears the dst-space quad but leaves pixels
		// outside that quad (but inside the AABB) untouched. The second one
		// (using the PictOpOver operator and the texture t as source) fills in
		// the quad and again does not touch the pixels outside.
		//
		// What X11/Render calls PictOpOutReverse is also known as dst-out. See
		// http://www.w3.org/TR/SVGCompositing/examples/compop-porterduff-examples.png
		// for a visualization.
		render.TriFan(t.s.xc, render.PictOpOutReverse, t.s.opaqueP, xp, 0, 0, 0, points[:])
	}
	render.TriFan(t.s.xc, render.PictOpOver, t.xp, xp, 0, 0, 0, points[:])
}

func trifanPoints(src2dst *f64.Aff3, sr image.Rectangle) [4]render.Pointfix {
	minX := float64(sr.Min.X)
	maxX := float64(sr.Max.X)
	minY := float64(sr.Min.Y)
	maxY := float64(sr.Max.Y)
	return [4]render.Pointfix{{
		f64ToFixed(src2dst[0]*minX + src2dst[1]*minY + src2dst[2]),
		f64ToFixed(src2dst[3]*minX + src2dst[4]*minY + src2dst[5]),
	}, {
		f64ToFixed(src2dst[0]*maxX + src2dst[1]*minY + src2dst[2]),
		f64ToFixed(src2dst[3]*maxX + src2dst[4]*minY + src2dst[5]),
	}, {
		f64ToFixed(src2dst[0]*maxX + src2dst[1]*maxY + src2dst[2]),
		f64ToFixed(src2dst[3]*maxX + src2dst[4]*maxY + src2dst[5]),
	}, {
		f64ToFixed(src2dst[0]*minX + src2dst[1]*maxY + src2dst[2]),
		f64ToFixed(src2dst[3]*minX + src2dst[4]*maxY + src2dst[5]),
	}}
}

func renderOp(op draw.Op) byte {
	if op == draw.Src {
		return render.PictOpSrc
	}
	return render.PictOpOver
}
