package main

import (
	"bytes"
	"fmt"
	"image"
	"image/jpeg"
	"image/png"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"

	"github.com/labstack/echo/v4"
	"github.com/nfnt/resize"
	"github.com/nickalie/go-webpbin"
)

func Conversion(input string) error {
	var width uint = 1920
	output := filepath.Base(input)
	outputdir := filepath.Dir(input)
	ext := filepath.Ext(output)
	output = output[0 : len(output)-len(ext)] // Remove file extension	            // Add .webp extension
	log.Println("Converting", input, "to", output+".webp")
	f, err := os.Open(input)
	if err != nil {
		return err
	}
	defer f.Close()
	var img image.Image

	switch ext {
	case ".webp":
		log.Println("Image already in WebP format")
		img, err = webpbin.Decode(f)
		if err != nil {
			return err
		}
	case ".png", ".PNG":
		// Convert from PNG
		img, err = png.Decode(f)
		if err != nil {
			return err
		}
	case ".jpeg", ".jpg", ".JPG", ".JPEG":
		// Convert from JPEG
		img, err = jpeg.Decode(f)
		if err != nil {
			return err
		}
	default:
		return fmt.Errorf("error: Unsupported file type: %s", ext)
	}

	err = image_creation(img, width, output, outputdir)
	if err != nil {
		return err
	}

	err = thumbnail_creation(img, output, outputdir)
	if err != nil {
		return err
	}

	fmt.Println("Conversion completed successfully")

	return nil
}

func image_creation(img image.Image, width uint, output string, outputdir string) error {
	// Resize the image
	resizedImg := resize.Resize(width, 0, img, resize.Lanczos3)

	// Create the output file
	outputPath := fmt.Sprintf("%s/%s.webp", outputdir, output)
	log.Println("Creating", outputPath)
	out, err := os.Create(outputPath)
	if err != nil {
		return err
	}
	defer out.Close()

	// Encode the resized image to the output file
	err = webpbin.Encode(out, resizedImg)
	if err != nil {
		return err
	}
	return nil
}

func thumbnail_creation(img image.Image, output string, outputdir string) error {
	// Resize the image
	resizedImg := resize.Resize(32, 0, img, resize.Lanczos3)

	// Create the output file
	outputPath := fmt.Sprintf("%s/thumbnail-%s.webp", outputdir, output)
	log.Println("Creating", outputPath)
	out, err := os.Create(outputPath)
	if err != nil {
		return err
	}
	defer out.Close()

	// Encode the resized image to the output file
	err = webpbin.Encode(out, resizedImg)
	if err != nil {
		return err
	}
	return nil
}

func ImageRoutes(e *echo.Echo) {

	e.GET("/initcwebp", func(c echo.Context) error {
		Conversion("test.jpg")
		return c.String(http.StatusOK, "Cwebp initialized")
	})

	e.GET("/images/list", func(c echo.Context) error {
		annunci := Db.GetActiveAnnunci()
		return c.JSON(http.StatusOK, annunci)
	})

	e.GET("/images/get/:cod/:imgNum", func(c echo.Context) error {
		cod := c.Param("cod")
		imgNum := c.Param("imgNum")
		thumb := c.QueryParam("thumbnail") == "true"
		widthStr := c.QueryParam("w")
		//quality := c.QueryParam("q")
		fmt.Printf("request for %s/%s, thumbnail=%t, w=%s\n", cod, imgNum, thumb, widthStr)
		prefix := ""
		if thumb {
			prefix = "thumbnail-"
		}

		Path := filepath.Join(imgbasepath, cod, imgNum, fmt.Sprintf("%s%s_%s.webp", prefix, cod, imgNum))
		fmt.Println(Path)
		if _, err := os.Stat(Path); os.IsNotExist(err) {

			fmt.Println("Image does not exist:", Path)
			// Serve a fallback image if the requested image is not found

			return FallbackImage(c)
		}
		if widthStr != "" {
			width, err := strconv.Atoi(widthStr)
			if err != nil {
				fmt.Println("Invalid width parameter:", widthStr)

				return FallbackImage(c)
			}
			f, err := os.Open(Path)
			if err != nil {
				return err
			}
			img, err := webpbin.Decode(f)
			if err != nil {
				fmt.Println("Failed to decode image:", err)
				return FallbackImage(c)
			}
			resizedImg := resize.Resize(uint(width), 0, img, resize.Lanczos3)
			buffer := new(bytes.Buffer)
			err = webpbin.Encode(buffer, resizedImg)
			if err != nil {
				fmt.Println("Failed to encode image:", err)
				return FallbackImage(c)
			}
			return c.Blob(http.StatusOK, "image/webp", buffer.Bytes())
		}

		return c.File(Path)

	})

	e.GET("/images/resetimages", func(c echo.Context) error {

		err := ImageManager.Reset()
		if err != nil {
			return c.String(http.StatusInternalServerError, err.Error())
		}

		return c.String(http.StatusOK, "OK")
	})

	e.POST("/image-option-toggle", func(c echo.Context) error {
		// Toggle the imageOption value
		imageOption = !imageOption

		// Convert the boolean value to a string and set the environment variable
		os.Setenv("IMAGEOPTION", strconv.FormatBool(imageOption))

		return c.String(http.StatusOK, "OK")
	})

}

func FallbackImage(c echo.Context) error {
	// Serve a fallback image if the requested image is not found
	fallbackPath := "fallback.webp" // Path to your fallback image
	if _, err := os.Stat(fallbackPath); os.IsNotExist(err) {
		return c.String(http.StatusNotFound, "Fallback image not found")
	}
	return c.File(fallbackPath)
}
