package main

import (
	"bytes"
	"context"
	"fmt"
	"github.com/flamego/flamego"
	"github.com/flamego/session"
	"github.com/flamego/template"
	"github.com/minio/minio-go/v7"
	"github.com/nfnt/resize"
	"github.com/rs/zerolog/log"
	"image"
	"image/jpeg"
	"math"
	"net/http"
	"os"
	"strconv"
	"time"
)

type File struct {
	ID int `db:"id"`
	GalleryId int `db:"gallery_id"`
	Path string `db:"path"`
	PathOrginalSize string `db:"path_orginal"`
}

func uploadImageForm(t template.Template, data template.Data , s session.Session, c flamego.Context) {
	id := c.Request().FormValue("id")
	if id == "" {
		galleries := []Gallery{}
		err := sqlConnection.Select(&galleries, "SELECT * FROM gallery WHERE owner_id = ? ORDER BY id DESC", s.Get("user_id"))
		if err != nil {
			panic(err)
		}

		data["galleries"] = galleries

		var list [][]Gallery
		var tmp []Gallery

		for _, g := range galleries {
			if len(tmp) == 6 {
				list = append(list, tmp)
				tmp = []Gallery{}
			}
			tmp = append(tmp, g)
		}
		list = append(list, tmp)

		data["list"] = list

		t.HTML(http.StatusOK, "file_gallery")
		return
	}
	data["id"] = id



	t.HTML(http.StatusOK, "file_upload")
}

/*
Something foobar das gibt es doch nicht
 */

func uploadImage(c flamego.Context, s session.Session) {
	//todo: check if loggedin
	//todo: check if gllery is owned by uploader
	file, fileHeader, err := c.Request().FormFile("file")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	galleryIdString := c.Request().FormValue("id")
	galleryId, err := strconv.Atoi(galleryIdString)
	if err != nil {
		panic(err)
	}

	path := fmt.Sprintf("/gallery/%v/%v/data/%v-%v", s.Get("user_id"), galleryId, time.Now().UnixNano(), fileHeader.Filename)
	pathOrignal := fmt.Sprintf("/gallery/%v/%v/data/%v-%v", s.Get("user_id"), galleryId, time.Now().UnixNano(), fileHeader.Filename)

	imgO, _ , err := image.Decode(file)
	if err != nil {
		panic(err)
	}

	newImage := imgO

	x := math.Max(float64(imgO.Bounds().Dx()), float64(imgO.Bounds().Dy()))
	if x > 1500 {
		if imgO.Bounds().Dx() > imgO.Bounds().Dy() {
			newImage = resize.Resize(1200, 0, imgO, resize.Lanczos3)
		} else {
			newImage = resize.Resize(0, 1200, imgO, resize.Lanczos3)
		}
		pathOrignal = fmt.Sprintf("/gallery/%v/%v/data/%v-o-%v", s.Get("user_id"), galleryId, time.Now().UnixNano(), fileHeader.Filename)
		uploadImageToS3(imgO, pathOrignal)
	}



	info, err := uploadImageToS3(newImage, path)
	if err != nil {
		panic(err)
	}

	_, err = sqlConnection.NamedExec("INSERT INTO `images` (gallery_id, path, path_orginal) VALUES (:gallery, :path, :path_orginal)", map[string]interface{}{
		"gallery": galleryId,
		"path": info.Key,
		"path_orginal": pathOrignal,
	})

	if err != nil {
		err2 := s3.RemoveObject(context.Background(), os.Getenv("S3_BUCKET"), info.Key, minio.RemoveObjectOptions{})
		if err2 != nil {
			log.Warn().Err(err).Msg("Cant remove Unused File from s3 stroage")
		}
		panic(err)
	}


	c.ResponseWriter().Write([]byte("ok"))
}

func uploadImageToS3(img image.Image, path string) (minio.UploadInfo, error) {
	buf := new(bytes.Buffer)
	//err := png.Encode(buf, img)
	o := jpeg.Options{
		Quality: 100,
	}
	err := jpeg.Encode(buf, img, &o)
	if err != nil {
		return minio.UploadInfo{}, err
	}
	//send_s3 := buf.Bytes()

	info, err := s3.PutObject(context.Background(), os.Getenv("S3_BUCKET"), path, buf, -1, minio.PutObjectOptions{})
	return info, err
}