package tins2021

import (
	"image"
	"image/color"

	"github.com/llgcode/draw2d/draw2dimg"
	"github.com/lucasb-eyer/go-colorful"
	"opslag.de/schobers/geom"
)

const hexagonRadius = TextureSize / 2

func Clamp(f float64) float64 {
	if f < 0 {
		return 0
	}
	if f > 1 {
		return 1
	}
	return f
}

func drawToGC(gc *draw2dimg.GraphicContext, points ...geom.PointF) {
	gc.MoveTo(points[0].XY())
	for _, p := range points[1:] {
		gc.LineTo(p.XY())
	}
	gc.Close()
}

func fillStrokeToGC(gc *draw2dimg.GraphicContext, color color.Color, points ...geom.PointF) {
	gc.SetStrokeColor(color)
	gc.SetFillColor(color)
	drawToGC(gc, points...)
	gc.FillStroke()
}

func GenerateCube(hexColor string) image.Image {
	im := image.NewRGBA(image.Rect(0, 0, 2*hexagonRadius, 2*hexagonRadius))

	normal := mustHexColor(hexColor)
	h, c, l := normal.Hcl()
	light := colorful.Hcl(h, c, Clamp(l+0.1)).Clamped()
	dark := colorful.Hcl(h, c, Clamp(l-0.1)).Clamped()

	center, points := Hexagon(hexagonRadius)

	gc := draw2dimg.NewGraphicContext(im)
	fillStrokeToGC(gc, dark, points[2], points[3], points[4], center)
	fillStrokeToGC(gc, normal, points[4], points[5], points[0], center)
	fillStrokeToGC(gc, light, points[0], points[1], points[2], center)

	return im
}

func GenerateHexagon(hexColor string) image.Image {
	im := image.NewRGBA(image.Rect(0, 0, 2*hexagonRadius, 2*hexagonRadius))
	color := mustHexColor(hexColor)
	center, points := Hexagon(hexagonRadius)

	gc := draw2dimg.NewGraphicContext(im)
	fillStrokeToGC(gc, color, points[2], points[3], points[4], center)
	fillStrokeToGC(gc, color, points[4], points[5], points[0], center)
	fillStrokeToGC(gc, color, points[0], points[1], points[2], center)

	return im
}

func Hexagon(radius float64) (geom.PointF, []geom.PointF) {
	points := make([]geom.PointF, 6)
	center := geom.PtF(radius, radius)
	for i := range points {
		a := geom.Pi * (float64(i)/3 + (1. / 6))
		points[i] = center.Add(geom.PtF(radius*geom.Cos(a), -radius*geom.Sin(a)))
	}
	return center, points
}

func GenerateHole(hexColor string) image.Image {
	im := image.NewRGBA(image.Rect(0, 0, 2*hexagonRadius, 2*hexagonRadius))

	normal := mustHexColor(hexColor)
	h, c, l := normal.Hcl()
	light := colorful.Hcl(h, c, Clamp(l+0.1)).Clamped()
	dark := colorful.Hcl(h, c, Clamp(l-0.1)).Clamped()

	center, points := Hexagon(hexagonRadius)

	gc := draw2dimg.NewGraphicContext(im)
	fillStrokeToGC(gc, dark, points[5], points[0], points[1], center)
	fillStrokeToGC(gc, normal, points[1], points[2], points[3], center)
	fillStrokeToGC(gc, light, points[3], points[4], points[5], center)

	return im
}

func strokeToGC(gc *draw2dimg.GraphicContext, color color.Color, points ...geom.PointF) {
	gc.SetStrokeColor(color)
	drawToGC(gc, points...)
	gc.Stroke()
}