package media

import (
	"fmt"
	"image"
	"regexp"
	"strconv"
	"strings"
)

var (
	sizeString = regexp.MustCompile(`([0-9]*)(x)?([0-9]*)`)
)

func SizeRequested(urlpath string, actual image.Rectangle) (image.Rectangle, error) {
	segments := strings.Count(urlpath, "/")
	if segments < 3 {
		return actual, nil
	}
	sizeSpec := strings.Split(urlpath, "/")[2]
	return ParseSizeString(sizeSpec, actual)
}

func ParseSizeString(str string, actual image.Rectangle) (image.Rectangle, error) {
	var err = fmt.Errorf("expected a size string {width}x{height}, saw %q", str)

	strs := sizeString.FindStringSubmatch(str)
	if len(strs) < 4 {
		return image.ZR, err
	}

	var w, h int
	var strconvErr error

	if strs[1] != "" {
		w, strconvErr = strconv.Atoi(strs[1])
		if strconvErr != nil {
			return image.ZR, err
		}
	}

	if strs[3] != "" {
		h, strconvErr = strconv.Atoi(strs[3])
		if strconvErr != nil {
			return image.ZR, err
		}
	}

	if strs[2] != "x" {
		// w was the only dimension given, so set it to the greater dimension
		// of the actual image size
		if actual.Dx() > actual.Dy() {
			h = 0
		} else {
			h = w
			w = 0
		}
	}

	return image.Rect(0, 0, w, h), nil
}

func NormalizeSize(media, requested image.Rectangle) image.Rectangle {
	if requested.Dx() == 0 && requested.Dy() == 0 {
		return media
	}
	if requested.Dy()%2 == 1 {
		requested.Max.Y--
	}
	if requested.Dx() != 0 && requested.Dy() != 0 {
		return requested
	}
	scaled := image.Rectangle{}
	if requested.Dx() == 0 {
		scaled.Max.Y = requested.Dy()
		scaled.Max.X = requested.Dy() * media.Dx() / media.Dy()
	}
	if requested.Dy() == 0 {
		scaled.Max.X = requested.Dx()
		scaled.Max.Y = requested.Dx() * media.Dy() / media.Dx()
		for scaled.Max.Y%2 == 1 {
			requested.Max.X--
			scaled.Max.X = requested.Dx()
			scaled.Max.Y = requested.Dx() * media.Dy() / media.Dx()
		}
	}
	return scaled
}
