package main

import (
	"image"
	"image/color"
	"math/rand"

	iu "git.nkpl.cc/twocookedfaggots/imageutils"
)

func square(side int) image.Rectangle { return image.Rect(0, 0, side, side) }

func Circles(b image.Rectangle, radius int) chan iu.Circle {
	ch := make(chan iu.Circle)
	go func() {
		defer close(ch)
		for {
			x, y := rand.Int()%b.Dx(), rand.Int()%b.Dy()
			dxdy := b.Dx() * b.Dy()
			r := rand.Int() % (dxdy / (dxdy / radius))
			ch <- iu.Circle{image.Point{x, y}, r}
		}
	}()
	return ch
}

var Opaque, Transparent = color.Alpha{0xff}, color.Alpha{0}

type xor struct{ dst, src image.Image }

func (t xor) ColorModel() color.Model { return t.dst.ColorModel() }
func (t xor) Bounds() image.Rectangle { return t.src.Bounds() }
func (t xor) At(x, y int) color.Color {
	dstColor := t.ColorModel().Convert(t.dst.At(x, y))
	srcColor := t.ColorModel().Convert(t.src.At(x, y))

	// xor operation (a || b) && !(a && b)
	if ((dstColor == color.Opaque) || (srcColor == color.Opaque)) &&
		!((dstColor == color.Opaque) && (srcColor == color.Opaque)) {
		return color.Opaque
	}
	return color.Transparent
}

var exchange = color.ModelFunc(
	func(c color.Color) color.Color {
		if color.Alpha16Model.Convert(c) == color.Transparent {
			return color.Opaque
		}
		return color.Transparent
	},
)

type Exchange struct{ image.Image }

func (e Exchange) ColorModel() color.Model { return color.Alpha16Model }
func (e Exchange) Bounds() image.Rectangle { return e.Image.Bounds() }
func (e Exchange) At(x, y int) color.Color {
	c := e.ColorModel().Convert(e.Image.At(x, y))
	return exchange.Convert(c)
}

var blackAndWhite = color.ModelFunc(
	func(c color.Color) color.Color {
		if color.Alpha16Model.Convert(c) == color.Transparent {
			return color.Black
		}
		return color.White
	},
)

// Black and white's alpha image.
type BlackAndWhite struct{ image.Image }

func (b BlackAndWhite) ColorModel() color.Model { return color.Gray16Model }
func (b BlackAndWhite) Bounds() image.Rectangle { return b.Image.Bounds() }
func (b BlackAndWhite) At(x, y int) color.Color {
	c := b.Image.At(x, y)
	return blackAndWhite.Convert(c)
}
