package main

// CATIA dosyalari (CATPart, CATProduct, CATDrawing, CATProcess) icine gomulu bir JPEG onizleme tasir;
// "Preview" kaydinin hemen yanindadir. Shell kucuk resim saglayicisi calismadiginda (bu durumda
// Explorer'daki onizleme yerine yalnizca tur simgesi gelir) bu gomulu onizleme okunup kucultulur.

import (
	"bytes"
	"encoding/base64"
	"errors"
	"image"
	"image/jpeg"
	"image/png"
	"os"
	"path/filepath"
	"strings"
)

const (
	catGomuluMaksBayt = 200 << 20 // bu boyutun ustundeki dosyalar okunmaz
	catGomuluPencere  = 8192      // "Preview" kaydindan sonra JPEG'in aranacagi bayt sayisi
)

var catUzantilari = map[string]bool{
	".catpart": true, ".catproduct": true, ".catdrawing": true, ".catprocess": true,
}

// catUzantiMi: dosya CATIA belgesi mi.
func catUzantiMi(ad string) bool {
	return catUzantilari[strings.ToLower(filepath.Ext(ad))]
}

// catGomuluOnizleme: dosyadaki gomulu JPEG onizlemeyi bulup en fazla boyutPx'e kucultur ve PNG data URL dondurur.
func catGomuluOnizleme(yol string, boyutPx int) (string, error) {
	st, err := os.Stat(yol)
	if err != nil {
		return "", err
	}
	if st.IsDir() || st.Size() > catGomuluMaksBayt {
		return "", errors.New("dosya gömülü önizleme için uygun değil")
	}
	veri, err := os.ReadFile(yol)
	if err != nil {
		return "", err
	}
	idx := bytes.Index(veri, []byte("Preview"))
	if idx < 0 {
		return "", errors.New("gömülü önizleme yok")
	}
	pencere := veri[idx:]
	if len(pencere) > catGomuluPencere {
		pencere = pencere[:catGomuluPencere]
	}
	j := bytes.Index(pencere, []byte{0xFF, 0xD8, 0xFF})
	if j < 0 {
		return "", errors.New("gömülü JPEG bulunamadı")
	}
	kaynak, err := jpeg.Decode(bytes.NewReader(pencere[j:]))
	if err != nil {
		return "", err
	}
	kucuk := kucult(kaynak, boyutPx)
	var buf bytes.Buffer
	if err := png.Encode(&buf, kucuk); err != nil {
		return "", err
	}
	return "data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes()), nil
}

// kucult: en uzun kenari boyutPx olacak sekilde en-yakin komsu yontemiyle kucultur.
func kucult(src image.Image, boyutPx int) *image.RGBA {
	b := src.Bounds()
	w, h := b.Dx(), b.Dy()
	if w <= 0 || h <= 0 {
		return image.NewRGBA(image.Rect(0, 0, 1, 1))
	}
	nw, nh := w, h
	if w > boyutPx || h > boyutPx {
		if w >= h {
			nw = boyutPx
			nh = h * boyutPx / w
		} else {
			nh = boyutPx
			nw = w * boyutPx / h
		}
	}
	if nw < 1 {
		nw = 1
	}
	if nh < 1 {
		nh = 1
	}
	out := image.NewRGBA(image.Rect(0, 0, nw, nh))
	for y := 0; y < nh; y++ {
		sy := b.Min.Y + y*h/nh
		for x := 0; x < nw; x++ {
			sx := b.Min.X + x*w/nw
			r, g, bb, a := src.At(sx, sy).RGBA()
			o := out.PixOffset(x, y)
			out.Pix[o] = uint8(r >> 8)
			out.Pix[o+1] = uint8(g >> 8)
			out.Pix[o+2] = uint8(bb >> 8)
			out.Pix[o+3] = uint8(a >> 8)
		}
	}
	return out
}
