package images

import (
	"image"
	"math"

	"golang.org/x/image/draw"
)

func scale(src image.Image, options Options) image.Image {
	// Set the expected size that you want:
	dst := image.NewRGBA(
		calculateFit(src.Bounds(), options),
	)

	// Resize:
	draw.ApproxBiLinear.Scale(dst, dst.Rect, src, src.Bounds(), draw.Over, nil)

	// Encode to `output`:
	return dst
}

// calculateFit returns the new dimensions (width, height) that fit within the
// provided Options without upscaling and while maintaining the aspect ratio.
func calculateFit(bounds image.Rectangle, opt Options) image.Rectangle {
	// If no limits are set, or the image is already smaller than the limits,
	// return original dimensions (No Upscaling).
	if (opt.Width == 0 || bounds.Max.X <= opt.Width) && (opt.Height == 0 || bounds.Max.Y <= opt.Height) {
		return bounds
	}

	// Calculate ratios for width and height
	ratioW := float64(opt.Width) / float64(bounds.Max.X)
	ratioH := float64(opt.Height) / float64(bounds.Max.Y)

	// Determine the scale factor
	var scale float64
	if opt.Width > 0 && opt.Height > 0 {
		// Use the smaller ratio to ensure it fits in both bounds
		scale = math.Min(ratioW, ratioH)
	} else if opt.Width > 0 {
		scale = ratioW
	} else if opt.Height > 0 {
		scale = ratioH
	} else {
		return bounds
	}

	return image.Rect(
		0,
		0,
		int(math.Round(float64(bounds.Max.X)*scale)),
		int(math.Round(float64(bounds.Max.Y)*scale)),
	)
}
