// Copyright 2016 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 example
// +build example

//
// This build tag means that "go install golang.org/x/exp/shiny/..." doesn't
// install this example program. Use "go run main.go" to run it or "go install
// -tags=example" to install it.

// Basicgl demonstrates the use of Shiny's glwidget.
package main

import (
	"encoding/binary"
	"fmt"
	"image"
	"image/color"
	"log"
	"math"

	"golang.org/x/exp/shiny/driver/gldriver"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/exp/shiny/unit"
	"golang.org/x/exp/shiny/widget"
	"golang.org/x/exp/shiny/widget/flex"
	"golang.org/x/exp/shiny/widget/glwidget"
	"golang.org/x/exp/shiny/widget/theme"
	"golang.org/x/image/colornames"
	"golang.org/x/mobile/gl"
)

func colorPatch(c color.Color, w, h unit.Value) *widget.Sizer {
	return widget.NewSizer(w, h, widget.NewUniform(theme.StaticColor(c), nil))
}

func main() {
	gldriver.Main(func(s screen.Screen) {
		t1, t2 := newTriangleGL(), newTriangleGL()
		defer t1.cleanup()
		defer t2.cleanup()

		body := widget.NewSheet(flex.NewFlex(
			colorPatch(colornames.Green, unit.Pixels(50), unit.Pixels(50)),
			widget.WithLayoutData(t1.w, flex.LayoutData{Grow: 1, Align: flex.AlignItemStretch}),
			colorPatch(colornames.Blue, unit.Pixels(50), unit.Pixels(50)),
			widget.WithLayoutData(t2.w, flex.LayoutData{MinSize: image.Point{80, 80}}),
			colorPatch(colornames.Green, unit.Pixels(50), unit.Pixels(50)),
		))

		if err := widget.RunWindow(s, body, &widget.RunWindowOptions{
			NewWindowOptions: screen.NewWindowOptions{
				Title: "BasicGL Shiny Example",
			},
		}); err != nil {
			log.Fatal(err)
		}
	})
}

func newTriangleGL() *triangleGL {
	t := new(triangleGL)
	t.w = glwidget.NewGL(t.draw)
	t.init()
	return t
}

type triangleGL struct {
	w *glwidget.GL

	program  gl.Program
	position gl.Attrib
	offset   gl.Uniform
	color    gl.Uniform
	buf      gl.Buffer

	green float32
}

func (t *triangleGL) init() {
	glctx := t.w.Ctx
	var err error
	t.program, err = createProgram(glctx, vertexShader, fragmentShader)
	if err != nil {
		log.Fatalf("error creating GL program: %v", err)
	}

	t.buf = glctx.CreateBuffer()
	glctx.BindBuffer(gl.ARRAY_BUFFER, t.buf)
	glctx.BufferData(gl.ARRAY_BUFFER, triangleData, gl.STATIC_DRAW)

	t.position = glctx.GetAttribLocation(t.program, "position")
	t.color = glctx.GetUniformLocation(t.program, "color")
	t.offset = glctx.GetUniformLocation(t.program, "offset")

	glctx.UseProgram(t.program)
	glctx.ClearColor(1, 0, 0, 1)
}

func (t *triangleGL) cleanup() {
	glctx := t.w.Ctx
	glctx.DeleteProgram(t.program)
	glctx.DeleteBuffer(t.buf)
}

func (t *triangleGL) draw(w *glwidget.GL) {
	glctx := t.w.Ctx

	glctx.Viewport(0, 0, w.Rect.Dx(), w.Rect.Dy())
	glctx.Clear(gl.COLOR_BUFFER_BIT)

	t.green += 0.01
	if t.green > 1 {
		t.green = 0
	}
	glctx.Uniform4f(t.color, 0, t.green, 0, 1)
	glctx.Uniform2f(t.offset, 0.2, 0.9)

	glctx.BindBuffer(gl.ARRAY_BUFFER, t.buf)
	glctx.EnableVertexAttribArray(t.position)
	glctx.VertexAttribPointer(t.position, coordsPerVertex, gl.FLOAT, false, 0, 0)
	glctx.DrawArrays(gl.TRIANGLES, 0, vertexCount)
	glctx.DisableVertexAttribArray(t.position)
	w.Publish()
}

// asBytes returns the byte representation of float32 values in the given byte
// order. byteOrder must be either binary.BigEndian or binary.LittleEndian.
func asBytes(byteOrder binary.ByteOrder, values ...float32) []byte {
	le := false
	switch byteOrder {
	case binary.BigEndian:
	case binary.LittleEndian:
		le = true
	default:
		panic(fmt.Sprintf("invalid byte order %v", byteOrder))
	}

	b := make([]byte, 4*len(values))
	for i, v := range values {
		u := math.Float32bits(v)
		if le {
			b[4*i+0] = byte(u >> 0)
			b[4*i+1] = byte(u >> 8)
			b[4*i+2] = byte(u >> 16)
			b[4*i+3] = byte(u >> 24)
		} else {
			b[4*i+0] = byte(u >> 24)
			b[4*i+1] = byte(u >> 16)
			b[4*i+2] = byte(u >> 8)
			b[4*i+3] = byte(u >> 0)
		}
	}
	return b
}

// createProgram creates, compiles, and links a gl.Program.
func createProgram(glctx gl.Context, vertexSrc, fragmentSrc string) (gl.Program, error) {
	program := glctx.CreateProgram()
	if program.Value == 0 {
		return gl.Program{}, fmt.Errorf("basicgl: no programs available")
	}

	vertexShader, err := loadShader(glctx, gl.VERTEX_SHADER, vertexSrc)
	if err != nil {
		return gl.Program{}, err
	}
	fragmentShader, err := loadShader(glctx, gl.FRAGMENT_SHADER, fragmentSrc)
	if err != nil {
		glctx.DeleteShader(vertexShader)
		return gl.Program{}, err
	}

	glctx.AttachShader(program, vertexShader)
	glctx.AttachShader(program, fragmentShader)
	glctx.LinkProgram(program)

	// Flag shaders for deletion when program is unlinked.
	glctx.DeleteShader(vertexShader)
	glctx.DeleteShader(fragmentShader)

	if glctx.GetProgrami(program, gl.LINK_STATUS) == 0 {
		defer glctx.DeleteProgram(program)
		return gl.Program{}, fmt.Errorf("basicgl: %s", glctx.GetProgramInfoLog(program))
	}
	return program, nil
}

func loadShader(glctx gl.Context, shaderType gl.Enum, src string) (gl.Shader, error) {
	shader := glctx.CreateShader(shaderType)
	if shader.Value == 0 {
		return gl.Shader{}, fmt.Errorf("basicgl: could not create shader (type %v)", shaderType)
	}
	glctx.ShaderSource(shader, src)
	glctx.CompileShader(shader)
	if glctx.GetShaderi(shader, gl.COMPILE_STATUS) == 0 {
		defer glctx.DeleteShader(shader)
		return gl.Shader{}, fmt.Errorf("basicgl: shader compile: %s", glctx.GetShaderInfoLog(shader))
	}
	return shader, nil
}

var triangleData = asBytes(binary.LittleEndian,
	0.0, 0.4, 0.0, // top left
	0.0, 0.0, 0.0, // bottom left
	0.4, 0.0, 0.0, // bottom right
)

const (
	coordsPerVertex = 3
	vertexCount     = 3
)

const vertexShader = `#version 100
uniform vec2 offset;

attribute vec4 position;
void main() {
	// offset comes in with x/y values between 0 and 1.
	// position bounds are -1 to 1.
	vec4 offset4 = vec4(2.0*offset.x-1.0, 1.0-2.0*offset.y, 0, 0);
	gl_Position = position + offset4;
}`

const fragmentShader = `#version 100
precision mediump float;
uniform vec4 color;
void main() {
	gl_FragColor = color;
}`
