package helper

import (
	"image/color"
)

func RGBtoLRGB(r, g, b uint32) (_, _, _ float64) {
	return Linearize(r), Linearize(g), Linearize(b)
}

func NRGBAtoNLRGBA(r, g, b, a uint32) (_, _, _, _ float64) {
	_r, _g, _b := RGBtoLRGB(r, g, b)
	return _r, _g, _b, float64(a) / 0xffff
}

func RGBAtoNLRGBA(r, g, b, a uint32) (_, _, _, _ float64) {
	switch a {
	case 0:
		return 0, 0, 0, 0
	case 0xffff:
		_r, _g, _b := RGBtoLRGB(r, g, b)
		return _r, _g, _b, 1
	default:
		// note that we round up here, as the inverse function, ToRGBA, rounds down.
		return NRGBAtoNLRGBA((r*0xffff+a-1)/a, (g*0xffff+a-1)/a, (b*0xffff+a-1)/a, a)
	}
}

func ColorToNLRGBA(c color.Color) (_, _, _, _ float64) {
	switch c := c.(type) {
	case color.NRGBA:
		return NRGBAtoNLRGBA(uint32(c.R)*0x101, uint32(c.G)*0x101, uint32(c.B)*0x101, uint32(c.A)*0x101)
	case color.NRGBA64:
		return NRGBAtoNLRGBA(uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A))
	case interface{ NLRGBA() (r, g, b, a float64) }:
		return c.NLRGBA()
	case interface{ NXYZA() (x, y, z, a float64) }:
		x, y, z, a := c.NXYZA()
		r, g, b := XYZtoLRGB(x, y, z)
		return r, g, b, a
	case interface {
		NOkLabA() (lightness, chromaA, chromaB, a float64)
	}:
		lightness, chromaA, chromaB, a := c.NOkLabA()
		r, g, b := LMStoLRGB(OkLabToLMS(lightness, chromaA, chromaB))
		return r, g, b, a

	case interface{ NRGBA() (r, g, b, a uint32) }:
		return NRGBAtoNLRGBA(c.NRGBA())
	default:
		return RGBAtoNLRGBA(c.RGBA())
	}
}

func LRGBtoRGB(r, g, b float64) (_, _, _ uint32) {
	r, g, b = ClampRGB(r, g, b)
	return Delinearize(r), Delinearize(g), Delinearize(b)
}

func NLRGBAtoNRGBA(r, g, b, a float64) (_, _, _, _ uint32) {
	_r, _g, _b := LRGBtoRGB(r, g, b)
	return _r, _g, _b, uint32(min(1, max(0, a))*0xffff + .5)
}

func NLRGBAtoRGBA(r, g, b, a float64) (_, _, _, _ uint32) {
	switch _r, _g, _b, _a := NLRGBAtoNRGBA(r, g, b, a); _a {
	case 0:
		return 0, 0, 0, 0
	case 0xffff:
		return _r, _g, _b, 0xffff
	default:
		return _r * _a / 0xffff, _g * _a / 0xffff, _b * _a / 0xffff, _a
	}
}