package main

import (
	"fmt"
	"html/template"
	"log"
	"net/http"
	"strconv"
)

// LanguageOption represents a language option for search
type LanguageOption struct {
	Code string
	Name string
}

var settings UserSettings

var languageOptions = []LanguageOption{
	{Code: "", Name: "Any Language"},
	{Code: "en", Name: "English"},
	{Code: "af", Name: "Afrikaans"},
	{Code: "ar", Name: "العربية (Arabic)"},
	{Code: "hy", Name: "Հայերեն (Armenian)"},
	{Code: "be", Name: "Беларуская (Belarusian)"},
	{Code: "bg", Name: "български (Bulgarian)"},
	{Code: "ca", Name: "Català (Catalan)"},
	{Code: "zh-CN", Name: "中文 (简体) (Chinese Simplified)"},
	{Code: "zh-TW", Name: "中文 (繁體) (Chinese Traditional)"},
	{Code: "hr", Name: "Hrvatski (Croatian)"},
	{Code: "cs", Name: "Čeština (Czech)"},
	{Code: "da", Name: "Dansk (Danish)"},
	{Code: "nl", Name: "Nederlands (Dutch)"},
	{Code: "eo", Name: "Esperanto"},
	{Code: "et", Name: "Eesti (Estonian)"},
	{Code: "tl", Name: "Filipino (Tagalog)"},
	{Code: "fi", Name: "Suomi (Finnish)"},
	{Code: "fr", Name: "Français (French)"},
	{Code: "de", Name: "Deutsch (German)"},
	{Code: "el", Name: "Ελληνικά (Greek)"},
	{Code: "iw", Name: "עברית (Hebrew)"},
	{Code: "hi", Name: "हिन्दी (Hindi)"},
	{Code: "hu", Name: "magyar (Hungarian)"},
	{Code: "is", Name: "íslenska (Icelandic)"},
	{Code: "id", Name: "Bahasa Indonesia (Indonesian)"},
	{Code: "it", Name: "italiano (Italian)"},
	{Code: "ja", Name: "日本語 (Japanese)"},
	{Code: "ko", Name: "한국어 (Korean)"},
	{Code: "lv", Name: "latviešu (Latvian)"},
	{Code: "lt", Name: "lietuvių (Lithuanian)"},
	{Code: "no", Name: "norsk (Norwegian)"},
	{Code: "fa", Name: "فارسی (Persian)"},
	{Code: "pl", Name: "polski (Polish)"},
	{Code: "pt", Name: "português (Portuguese)"},
	{Code: "ro", Name: "română (Romanian)"},
	{Code: "ru", Name: "русский (Russian)"},
	{Code: "sr", Name: "српски (Serbian)"},
	{Code: "sk", Name: "slovenčina (Slovak)"},
	{Code: "sl", Name: "slovenščina (Slovenian)"},
	{Code: "es", Name: "español (Spanish)"},
	{Code: "sw", Name: "Kiswahili (Swahili)"},
	{Code: "sv", Name: "svenska (Swedish)"},
	{Code: "th", Name: "ไทย (Thai)"},
	{Code: "tr", Name: "Türkçe (Turkish)"},
	{Code: "uk", Name: "українська (Ukrainian)"},
	{Code: "vi", Name: "Tiếng Việt (Vietnamese)"},
}

func handleSearch(w http.ResponseWriter, r *http.Request) {
	query, safe, lang, searchType, page := parseSearchParams(r)

	settings = loadUserSettings(w, r)

	theme := r.URL.Query().Get("theme")
	if theme != "" {
		settings.Theme = theme
		saveUserSettings(w, settings)
	} else if settings.Theme == "" {
		settings.Theme = "dark"
	}

	if safe != "" && safe != settings.SafeSearch {
		settings.SafeSearch = safe
		saveUserSettings(w, settings)
	}

	// Update site language if provided, or use existing settings
	if lang != "" && lang != settings.SiteLanguage {
		settings.SiteLanguage = lang
		saveUserSettings(w, settings)
	} else if settings.SiteLanguage == "" {
		settings.SiteLanguage = normalizeLangCode(r.Header.Get("Accept-Language"))
		saveUserSettings(w, settings)
	}

	// Update search language (can be empty)
	searchLang := r.URL.Query().Get("search_lang")
	if searchLang != settings.SearchLanguage {
		settings.SearchLanguage = searchLang
		saveUserSettings(w, settings)
	}

	switch settings.Theme {
	case "dark", "black", "night", "latte":
		settings.IsThemeDark = true
	default:
		settings.IsThemeDark = false
	}

	InitializeLanguage(settings.SiteLanguage)

	// Translate the "Any Language" option after initialization
	for i, option := range languageOptions {
		if option.Code == "" {
			languageOptions[i].Name = Translate("any_language")
		}
	}

	// Determine the paths for SVG and PNG icons
	iconPathSVG, iconPathPNG := GetIconPath()

	if query == "" {
		data := struct {
			LanguageOptions   []LanguageOption
			CurrentLang       string
			CurrentSearchLang string
			Theme             string
			Safe              string
			IsThemeDark       bool
			IconPathSVG       string
			IconPathPNG       string
		}{
			LanguageOptions:   languageOptions,
			CurrentLang:       settings.SiteLanguage,
			CurrentSearchLang: settings.SearchLanguage,
			Theme:             settings.Theme,
			Safe:              settings.SafeSearch,
			IsThemeDark:       settings.IsThemeDark,
			IconPathSVG:       iconPathSVG,
			IconPathPNG:       iconPathPNG,
		}

		// Add Translate to the template functions
		tmpl, err := template.New("search.html").Funcs(template.FuncMap{
			"translate": Translate,
		}).ParseFiles("templates/search.html")
		if err != nil {
			printErr("Error parsing template: %v", err)
			http.Error(w, Translate("internal_server_error"), http.StatusInternalServerError)
			return
		}

		err = tmpl.Execute(w, data)
		if err != nil {
			printErr("Error executing template: %v", err)
			http.Error(w, Translate("internal_server_error"), http.StatusInternalServerError)
		}
		return
	}

	// Handle different search types
	switch searchType {
	case "image":
		handleImageSearch(w, settings, query, page)
	case "video":
		handleVideoSearch(w, settings, query, page)
	case "map":
		handleMapSearch(w, settings, query)
	case "forum":
		handleForumsSearch(w, settings, query, page)
	case "file":
		handleFileSearch(w, settings, query, page)
	case "text":
		fallthrough
	default:
		HandleTextSearch(w, settings, query, page)
	}
}

func parseSearchParams(r *http.Request) (query, safe, lang, searchType string, page int) {
	if r.Method == "GET" {
		query = r.URL.Query().Get("q")
		safe = r.URL.Query().Get("safe")
		lang = r.URL.Query().Get("lang")
		searchType = r.URL.Query().Get("t")
		pageStr := r.URL.Query().Get("p")
		page = parsePageParameter(pageStr)
	} else if r.Method == "POST" {
		query = r.FormValue("q")
		safe = r.FormValue("safe")
		lang = r.FormValue("lang")
		searchType = r.FormValue("t")
		pageStr := r.FormValue("p")
		page = parsePageParameter(pageStr)
	}

	if searchType == "" {
		searchType = "text"
	}

	return
}

func parsePageParameter(pageStr string) int {
	page, err := strconv.Atoi(pageStr)
	if err != nil || page < 1 {
		page = 1
	}
	return page
}

func runServer() {
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
	http.HandleFunc("/", handleSearch)
	http.HandleFunc("/search", handleSearch)
	http.HandleFunc("/suggestions", handleSuggestions)
	http.HandleFunc("/imgproxy", handleImageProxy)
	http.HandleFunc("/node", handleNodeRequest)
	http.HandleFunc("/settings", handleSettings)
	http.HandleFunc("/save-settings", handleSaveSettings)
	http.HandleFunc("/image_cache/", handleCachedImages)
	http.HandleFunc("/image_status", handleImageStatus)
	http.HandleFunc("/opensearch.xml", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/opensearchdescription+xml")
		http.ServeFile(w, r, "static/opensearch.xml")
	})

	printMessage("Server is listening on http://localhost:%d", config.Port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", config.Port), nil))
}