package mediaprovider

import (
	"bytes"
	"encoding/base64"
	"errors"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"strings"

	"github.com/gabriel-vasile/mimetype"
	"github.com/gen2brain/avif"
	"golang.org/x/image/draw"
	"golang.org/x/image/webp"
)

var ErrUnknownImageType = errors.New("unknown image format")

func Compress(dataReader io.Reader, mimeType *string) (io.Reader, error) {
	data, err := io.ReadAll(dataReader)
	if err != nil {
		return nil, err
	}
	if mimeType == nil {
		*mimeType = mimetype.Detect(data).String()
	}
	uberType, subType, _ := strings.Cut(*mimeType, "/")
	var dataOut []byte
	switch uberType {
	case "text":
	case "application":
	case "image":
		dataOut, err = compressImage(data, subType, 1280, 720)
	case "video":
		dataOut, err = compressVideo(data, subType)
	case "audio":
	case "font":
	default:
	}
	if err != nil && err != ErrUnknownImageType {
		return nil, err
	}
	dataOut = compressBase64(dataOut)
	return bytes.NewReader(dataOut), nil
}

func compressVideo(dataIn []byte, subType string) (dataOut []byte, err error) {
	// TODO: Implement me
	panic("Implement me")
}

func compressImage(dataIn []byte, subType string, maxSizeX, maxSizeY uint) (dataOut []byte, err error) {
	imageSize := image.Rect(0, 0, int(maxSizeX), int(maxSizeY))
	dst := image.NewRGBA(imageSize)
	var sourceImage image.Image
	switch subType {
	case "png":
		sourceImage, err = png.Decode(bytes.NewReader(dataIn))
		if err != nil {
			return nil, err
		}
	case "jpg", "jpeg":
		sourceImage, err = jpeg.Decode(bytes.NewReader(dataIn))
	case "webp":
		sourceImage, err = webp.Decode(bytes.NewReader(dataIn))
	case "avif":
		sourceImage, err = avif.Decode(bytes.NewReader(dataIn))
	default:
		return nil, ErrUnknownImageType
	}
	if err != nil {
		return nil, err
	}

	draw.CatmullRom.Scale(dst, imageSize, sourceImage, sourceImage.Bounds(), draw.Src, nil)
	return dst.Pix, nil
}

func compressBase64(dataIn []byte) []byte {
	result := []byte{}
	base64.StdEncoding.Encode(result, dataIn)
	return result
}
