package controller

import (
	"bytes"
	"chonho/config"
	_const "chonho/const"
	_error "chonho/pkg/c_error"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"image"
	"image/color"
	"image/draw"
	_ "image/gif"
	"image/jpeg"
	_ "image/png"
	"io"
	"mime/multipart"
	"os"
	"time"
)

type UploadController struct {
	Controller
}

func NewUploadController() *UploadController {
	return &UploadController{}
}

// Upload godoc
// @Summary Upload single file
// @Tags Upload
// @ID upload
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "The file to upload"
// @Success 200 {object} entity.UploadResponse
// @Failure 400 {object} entity.Response
// @Router /upload [post]
// @Security ApiVersion
// @Security AppVersion
// @Security AppPlatform
func (c *UploadController) Upload(ctx *gin.Context) {
	file, err := ctx.FormFile("file")
	if err != nil {
		c.Failure(ctx, _error.New(_const.UploadError, err.Error()))
		return
	}

	fileName := uuid.New().String() + ".jpg"
	subPath := time.Now().Format("2006/01")
	localPath := config.StoragePath + "/" + subPath + "/" + fileName
	publicUrl := config.StorageDomain + "/" + subPath + "/" + fileName

	if _, err := os.Stat(config.StoragePath + "/" + subPath); os.IsNotExist(err) {
		if err := os.MkdirAll(config.StoragePath+"/"+subPath, os.ModePerm); err != nil {
			c.Failure(ctx, _error.New(_const.UploadError, err.Error()))
			return
		}
	}

	//if err := ctx.SaveUploadedFile(file, localPath); err != nil {
	//	c.Failure(ctx, _error.New(_const.UploadError, err.Error()))
	//	return
	//}

	if err := saveJPG(file, localPath); err != nil {
		c.Failure(ctx, _error.New(_const.UploadError, err.Error()))
		return
	}

	c.WrapResponse(ctx, publicUrl, nil)
}

func saveJPG(uploadFile *multipart.FileHeader, dst string) error {
	file, err := uploadFile.Open()
	if err != nil {
		return err
	}
	defer func(file multipart.File) {
		_ = file.Close()
	}(file)

	buf := bytes.NewBuffer(nil)
	if _, err := io.Copy(buf, file); err != nil {
		return err
	}

	imgSrc, _, err := image.Decode(buf)
	if err != nil {
		return err
	}

	// create a new Image with the same dimension of PNG image
	newImg := image.NewRGBA(imgSrc.Bounds())

	// we will use white background to replace PNG's transparent background
	// you can change it to whichever color you want with
	// a new color.RGBA{} and use image.NewUniform(color.RGBA{<fill in color>}) function
	draw.Draw(newImg, newImg.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)

	// paste PNG image OVER to newImage
	draw.Draw(newImg, newImg.Bounds(), imgSrc, imgSrc.Bounds().Min, draw.Over)

	// create new out JPEG file
	jpgImgFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer func(jpgImgFile *os.File) {
		_ = jpgImgFile.Close()
	}(jpgImgFile)

	err = jpeg.Encode(jpgImgFile, newImg, &jpeg.Options{
		Quality: 80,
	})

	if err != nil {
		return err
	}

	return nil
}
