//go:build windows

package main

// Dosya simgeleri: Explorer'daki tur simgesi (Shell IShellItemImageFactory, SIIGBF_ICONONLY).
// Ayni uzantinin simgesi bellekte tutulur (onbellek); exe/kisayol gibi her dosyada farkli olan simgeler onbellege alinmaz.

import (
	"encoding/json"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
)

// Her dosyaya ozel simgeler: onbellege alinmaz.
var simgeOnbellekDisi = map[string]bool{
	".exe": true, ".lnk": true, ".ico": true, ".url": true, ".msi": true, ".scr": true, ".appref-ms": true,
}

var (
	simgeMu       sync.Mutex
	simgeOnbellek = map[string]string{}
)

// simgeAcik: ayarda "simgeGoster" acik mi.
func simgeAcik(ayar json.RawMessage) bool {
	var s struct {
		SimgeGoster bool `json:"simgeGoster"`
	}
	if len(ayar) == 0 || json.Unmarshal(ayar, &s) != nil {
		return false
	}
	return s.SimgeGoster
}

// simgeAl: bir dosyanin (ya da klasorun) simgesi. Onbellek anahtari uzantidir; klasorler ayri tutulur.
func simgeAl(tam, anahtar string, onbellege bool) string {
	if onbellege {
		simgeMu.Lock()
		v, ok := simgeOnbellek[anahtar]
		simgeMu.Unlock()
		if ok {
			return v
		}
	}
	s, err := kabukiGoruntu(tam, simgePx, siiGbfIconOnly)
	if err != nil {
		s = ""
	}
	if onbellege {
		simgeMu.Lock()
		simgeOnbellek[anahtar] = s
		simgeMu.Unlock()
	}
	return s
}

// simgeMaksDeneme: bir aramada Shell'e en fazla kac simge sorgusu gidecegi (onbellekteki simgeler sayilmaz).
const simgeMaksDeneme = 100

// simgeOnbellekYok: anahtar onbellekte yoksa true (yani Shell'e sorgu gidecek).
func simgeOnbellekYok(anahtar string) bool {
	simgeMu.Lock()
	defer simgeMu.Unlock()
	_, ok := simgeOnbellek[anahtar]
	return !ok
}

// simgeleriEkle: arama sonucundaki her oge icin "simge" alani ekler. Toplam boyut sinirlidir.
func simgeleriEkle(veri json.RawMessage) json.RawMessage {
	var s struct {
		TotalResults int              `json:"totalResults"`
		Results      []map[string]any `json:"results"`
	}
	if err := json.Unmarshal(veri, &s); err != nil {
		return veri
	}
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()
	cikis, err := comBaslat()
	if err != nil {
		return veri
	}
	defer cikis()

	toplam := 0
	deneme := 0
	for _, r := range s.Results {
		if deneme >= simgeMaksDeneme {
			break
		}
		ad, _ := r["name"].(string)
		yol, _ := r["path"].(string)
		if ad == "" {
			continue
		}
		tam := ad
		if yol != "" {
			tam = yol + `\` + ad
		}
		var anahtar string
		onbellege := true
		if r["type"] == "folder" {
			anahtar = "klasor:"
		} else {
			anahtar = strings.ToLower(filepath.Ext(ad))
			if simgeOnbellekDisi[anahtar] {
				onbellege = false
			}
		}
		if !onbellege || simgeOnbellekYok(anahtar) {
			deneme++
		}
		simge := simgeAl(tam, anahtar, onbellege)
		if simge == "" {
			continue
		}
		if toplam+len(simge) > simgeToplamLimit {
			break
		}
		toplam += len(simge)
		r["simge"] = simge
	}
	out, err := json.Marshal(s)
	if err != nil {
		return veri
	}
	return out
}
