package wpdf

import (
	"gogs.mikescher.com/BlackForestBytes/goext/dataext"
	"gogs.mikescher.com/BlackForestBytes/goext/langext"
)

type PDFLineOpt struct {
	lineWidth *float64
	drawColor *PDFColor
	alpha     *dataext.Tuple[float64, PDFBlendMode]
	capStyle  *PDFLineCapStyle
	debug     *bool
}

func NewPDFLineOpt() *PDFLineOpt {
	return &PDFLineOpt{}
}

func (opt *PDFLineOpt) LineWidth(v float64) *PDFLineOpt {
	opt.lineWidth = &v
	return opt
}

func (opt *PDFLineOpt) DrawColor(cr, cg, cb int) *PDFLineOpt {
	opt.drawColor = langext.Ptr(rgbToColor(cr, cg, cb))
	return opt
}

func (opt *PDFLineOpt) DrawColorHex(c uint32) *PDFLineOpt {
	opt.drawColor = langext.Ptr(hexToColor(c))
	return opt
}

func (opt *PDFLineOpt) Alpha(alpha float64, blendMode PDFBlendMode) *PDFLineOpt {
	opt.alpha = &dataext.Tuple[float64, PDFBlendMode]{V1: alpha, V2: blendMode}
	return opt
}

func (opt *PDFLineOpt) CapButt() *PDFLineOpt {
	opt.capStyle = langext.Ptr(CapButt)
	return opt
}

func (opt *PDFLineOpt) CapSquare() *PDFLineOpt {
	opt.capStyle = langext.Ptr(CapSquare)
	return opt
}

func (opt *PDFLineOpt) CapRound() *PDFLineOpt {
	opt.capStyle = langext.Ptr(CapRound)
	return opt
}

func (opt *PDFLineOpt) Debug(v bool) *PDFLineOpt {
	opt.debug = &v
	return opt
}

func (b *WPDFBuilder) Line(x1 float64, y1 float64, x2 float64, y2 float64, opts ...*PDFLineOpt) {
	var lineWidth *float64
	var drawColor *PDFColor
	var alphaOverride *dataext.Tuple[float64, PDFBlendMode]
	capStyle := CapButt
	debug := b.debug

	for _, opt := range opts {
		lineWidth = langext.CoalesceOpt(opt.lineWidth, lineWidth)
		drawColor = langext.CoalesceOpt(opt.drawColor, drawColor)
		alphaOverride = langext.CoalesceOpt(opt.alpha, alphaOverride)
		capStyle = langext.Coalesce(opt.capStyle, capStyle)
		debug = langext.Coalesce(opt.debug, debug)
	}

	if lineWidth != nil {
		old := b.GetLineWidth()
		b.SetLineWidth(*lineWidth)
		defer func() { b.SetLineWidth(old) }()
	}

	if drawColor != nil {
		oldR, oldG, oldB := b.GetDrawColor()
		b.SetDrawColor(drawColor.R, drawColor.G, drawColor.B)
		defer func() { b.SetDrawColor(oldR, oldG, oldB) }()
	}

	if alphaOverride != nil {
		oldA, oldBMS := b.b.GetAlpha()
		b.b.SetAlpha(alphaOverride.V1, string(alphaOverride.V2))
		defer func() { b.b.SetAlpha(oldA, oldBMS) }()
	}

	b.b.SetLineCapStyle(string(capStyle))

	b.b.Line(x1, y1, x2, y2)
}