package main

// Eklenti sistemi: her yerel yetenek (Everything, CATIA, ...) bir eklenti olarak kaydedilir.
// Kapi sirasi: ana anahtar acik mi -> bu site icin sureli yetki var mi -> hiz siniri -> calistir.
// Her karar olay gunlugune yazilir.
// Yeni eklenti: izin anahtarini izin.go'ya ekleyin, asagidaki init icinde kaydini yapin.

import (
	"net/http"
)

type eklenti struct {
	anahtar  string // izin anahtari
	ad       string // gosterim adi
	aciklama string // kisa aciklama
	kapsam   string // ne yapabildigini acikca soyler
	yol      string // HTTP yolu
	isleyici http.HandlerFunc
}

var eklentiListesi []eklenti

func eklentiKaydet(e eklenti) {
	eklentiListesi = append(eklentiListesi, e)
}

// eklentileriKur: her eklentiyi oturum + token + yetki kapisi arkasina baglar.
func eklentileriKur(mux *http.ServeMux) {
	for _, e := range eklentiListesi {
		mux.HandleFunc(e.yol, korumali(oturumGerekli(yetkiKapisi(e.anahtar, e.isleyici))))
	}
	mux.HandleFunc("/eklentiler", korumali(oturumGerekli(eklentilerHandler)))
}

func yetkiKapisi(anahtar string, h http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		site := tokenOzeti(r.Header.Get("X-Bridge-Token"))
		kisa := site
		if len(kisa) > 8 {
			kisa = kisa[:8]
		}
		profil := profilDe(r)
		if !izinOkuProfil(profil).Acik(anahtar) {
			olayLog("eklenti reddedildi (ana izin kapali): %s, site %s", anahtar, kisa)
			http.Error(w, anahtar+" izni kapali", http.StatusForbidden)
			return
		}
		if !yetkiGecerliMiProfil(profil, anahtar, site) {
			olayLog("eklenti reddedildi (site yetkisi yok ya da suresi doldu): %s, site %s", anahtar, kisa)
			http.Error(w, "bu site icin yetki yok ya da suresi doldu", http.StatusForbidden)
			return
		}
		if !hizIzinVer(anahtar, site) {
			olayLog("eklenti hiz siniri asildi: %s, site %s", anahtar, kisa)
			http.Error(w, "cok fazla istek", http.StatusTooManyRequests)
			return
		}
		olayLog("eklenti cagrildi: %s, site %s", anahtar, kisa)
		h(w, r)
	}
}

type eklentiDurumu struct {
	Anahtar  string `json:"anahtar"`
	Ad       string `json:"ad"`
	Aciklama string `json:"aciklama"`
	Kapsam   string `json:"kapsam"`
	Acik     bool   `json:"acik"`
}

// eklentilerHandler: kayitli eklentileri, kapsamlarini ve ana anahtar durumunu listeler (yalnizca okuma).
func eklentilerHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "yalnizca GET", http.StatusMethodNotAllowed)
		return
	}
	y := izinOkuProfil(profilDe(r))
	liste := make([]eklentiDurumu, 0, len(eklentiListesi))
	for _, e := range eklentiListesi {
		liste = append(liste, eklentiDurumu{e.anahtar, e.ad, e.aciklama, e.kapsam, y.Acik(e.anahtar)})
	}
	yazJSON(w, http.StatusOK, liste)
}

func init() {
	eklentiKaydet(eklenti{
		anahtar:  "everythingAra",
		ad:       "Everything",
		aciklama: "Dosya adi aramasi",
		kapsam:   "Yalnizca dosya adlari aranir. Dosya icerigini eklenti kendisi acip okumaz; kucuk onizlemeler Windows'un kendi ozelliginden gelir. En fazla 30 sonuc, arama metni en fazla 200 karakter.",
		yol:      "/everything/ara",
		isleyici: everythingAraHandler,
	})
	eklentiKaydet(eklenti{
		anahtar:  "catiaAc",
		ad:       "CATIA",
		aciklama: "CATIA calisma durumu",
		kapsam:   "Yalnizca CATIA'nin acik olup olmadigi okunur. Hicbir sey baslatilmaz veya degistirilmez.",
		yol:      "/catia/durum",
		isleyici: catiaDurumHandler,
	})
}
