package gui

// desiresGui_Mental.go implements pages to manage a user's Mental mate desires

import "fyne.io/fyne/v2"
import "fyne.io/fyne/v2/container"
import "fyne.io/fyne/v2/layout"
import "fyne.io/fyne/v2/theme"
import "fyne.io/fyne/v2/widget"

import "seekia/internal/desires/myLocalDesires"
import "seekia/internal/encoding"
import "seekia/internal/helpers"
import "seekia/internal/worldLanguages"

import "strings"
import "errors"
import "slices"


func setChooseDesiresCategoryPage_Mental(window fyne.Window, previousPage func()){

	currentPage := func(){setChooseDesiresCategoryPage_Mental(window, previousPage)}

	title := getPageTitleCentered(translate("My Mate Desires - Mental"))

	backButton := getBackButtonCentered(previousPage)

	languageButton := widget.NewButton(translate("Language"), func(){
			setChooseDesiresPage_Language(window, currentPage)
		})

	genderIdentityButton := widget.NewButton(translate("Gender Identity"), func(){
			setChooseDesiresPage_GenderIdentity(window, currentPage)
		})
	petsButton := widget.NewButton(translate("Pets"), func(){
			setChooseDesiresPage_Pets(window, currentPage)
		})

	buttonsGrid := getContainerCentered(container.NewGridWithColumns(1, languageButton, genderIdentityButton, petsButton))

	buttonsGridPadded := container.NewPadded(buttonsGrid)

	page := container.NewVBox(title, backButton, widget.NewSeparator(), buttonsGridPadded)

	setPageContent(page, window)
}



func setChooseDesiresPage_Language(window fyne.Window, previousPage func()){

	currentPage := func(){setChooseDesiresPage_Language(window, previousPage)}

	title := getPageTitleCentered("My Mate Desires - Mental")

	backButton := getBackButtonCentered(previousPage)

	subtitle := getPageSubtitleCentered(translate("Language"))

	description1 := getLabelCentered("Choose the languages that you desire.")
	description2 := getLabelCentered("This refers to the languages that a user can speak.")
	description3 := getLabelCentered("For example, add English if you desire someone who can speak it.")

	getSelectedLanguagesSection := func()(*fyne.Container, error){

		getCurrentDesiredChoicesList := func()([]string, error){

			currentChoicesListExists, currentChoicesList, err := myLocalDesires.GetDesire("Language")
			if (err != nil) { return nil, err }		
			if (currentChoicesListExists == false){

				emptyList := make([]string, 0)
				return emptyList, nil
			}
			//currentChoicesList is a "+" separated list of choices
			// Each choice option is encoded in base64 (except for "Other")
			currentDesiredChoicesList := strings.Split(currentChoicesList, "+")

			return currentDesiredChoicesList, nil
		}

		currentDesiredChoicesList, err := getCurrentDesiredChoicesList()
		if (err != nil) { return nil, err }

		addLanguageButton := getWidgetCentered(widget.NewButtonWithIcon("Add Language", theme.ContentAddIcon(), func(){

				onSubmitFunction := func(_ int, newLanguagePrimaryName string)error{

					newLanguageNameBase64 := encoding.EncodeBytesToBase64String([]byte(newLanguagePrimaryName))

					newLanguagesList := helpers.AddItemToStringListAndAvoidDuplicate(currentDesiredChoicesList, newLanguageNameBase64)

					newDesireString := strings.Join(newLanguagesList, "+")

					err = myLocalDesires.SetDesire("Language", newDesireString)
					if (err != nil){ return err }

					return nil	
				}

				setChooseDesiresPage_AddLanguage(window, onSubmitFunction, currentPage, currentPage)
			}))

		allowOtherCheck := widget.NewCheck("Allow Other", func(response bool){

				getNewChoicesList := func()[]string{
	
					if (response == false){

						newList, _ := helpers.DeleteAllMatchingItemsFromList(currentDesiredChoicesList, "Other")
						return newList
					}

					newList := helpers.AddItemToStringListAndAvoidDuplicate(currentDesiredChoicesList, "Other")

					return newList
				}

				newList := getNewChoicesList()

				if (len(newList) == 0){
					err := myLocalDesires.DeleteDesire("Language")
					if (err != nil){
						setErrorEncounteredPage(window, err, currentPage)
						return
					}
					currentPage()
					return
				}

				newDesireValueString := strings.Join(newList, "+")

				err := myLocalDesires.SetDesire("Language", newDesireValueString)
				if (err != nil){
					setErrorEncounteredPage(window, err, currentPage)
					return
				}
				currentPage()
			})

		allowOtherIsSelected := slices.Contains(currentDesiredChoicesList, "Other")
		if (allowOtherIsSelected == true){
			allowOtherCheck.Checked = true
		}

		allowOtherHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
				setAllowOtherExplainerPage(window, currentPage)
			})

		allowOtherRow := container.NewHBox(layout.NewSpacer(), allowOtherCheck, allowOtherHelpButton, layout.NewSpacer())

		getAnyLanguageIsSelectedBool := func()bool{

			if (len(currentDesiredChoicesList) == 0){
				return false
			}
			if (len(currentDesiredChoicesList) == 1){
				onlyValue := currentDesiredChoicesList[0]
				if (onlyValue == "Other"){
					return false
				}
			}
			return true
		}

		anyLanguageIsSelected := getAnyLanguageIsSelectedBool()
		if (anyLanguageIsSelected == false){

			noLanguagesLabel := getBoldLabelCentered("No languages selected.")

			selectedLanguagesSection := container.NewVBox(noLanguagesLabel, addLanguageButton, widget.NewSeparator(), allowOtherRow)

			return selectedLanguagesSection, nil
		}

		myDesiredLanguagesLabel := getItalicLabelCentered("My Desired Languages:")

		languageNameColumn := container.NewVBox(widget.NewSeparator())

		deleteButtonsColumn := container.NewVBox(widget.NewSeparator())

		for _, languageNameBase64 := range currentDesiredChoicesList{

			if (languageNameBase64 == "Other"){
				continue
			}

			languageName, err := encoding.DecodeBase64StringToUnicodeString(languageNameBase64)
			if (err != nil){
				return nil, errors.New("My current language desire is malformed: Contains invalid language: " + languageNameBase64)
			}

			languageNameLabel := getBoldLabelCentered(translate(languageName))

			deleteLanguageButton := widget.NewButtonWithIcon("", theme.DeleteIcon(), func(){

					newDesiredLanguagesList, _ := helpers.DeleteAllMatchingItemsFromList(currentDesiredChoicesList, languageNameBase64)

					if (len(newDesiredLanguagesList) == 0){

						err := myLocalDesires.DeleteDesire("Language")
						if (err != nil){
							setErrorEncounteredPage(window, err, currentPage)
							return
						}
						currentPage()
						return				
					}

					newDesireValueString := strings.Join(newDesiredLanguagesList, "+")

					err := myLocalDesires.SetDesire("Language", newDesireValueString)
					if (err != nil){
						setErrorEncounteredPage(window, err, currentPage)
						return
					}
					currentPage()
				})

			languageNameColumn.Add(languageNameLabel)
			deleteButtonsColumn.Add(deleteLanguageButton)

			languageNameColumn.Add(widget.NewSeparator())
			deleteButtonsColumn.Add(widget.NewSeparator())
		}

		languagesGrid := container.NewHBox(layout.NewSpacer(), languageNameColumn, deleteButtonsColumn, layout.NewSpacer())

		//TODO: Add option for requiring a user to fulfill all of your chosen languages
		// For example, a user could only search for people who speak both English and French

		selectedLanguagesSection := container.NewVBox(addLanguageButton, widget.NewSeparator(), myDesiredLanguagesLabel, languagesGrid, widget.NewSeparator(), allowOtherRow)

		return selectedLanguagesSection, nil
	}

	selectedLanguagesSection, err := getSelectedLanguagesSection()
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, "Language", true)
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
			setViewMyMateDesireStatisticsPage(window, "Language", "Language", false, "", "", currentPage)
		}))
	
	page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), selectedLanguagesSection, widget.NewSeparator(), filterOptionsSection, widget.NewSeparator(), viewStatisticsButton)

	setPageContent(page, window)
}

//Inputs:
//	-fyne.Window
//	-func(int, string)error: The function to be executed when a choice is selected
//		-Int: Language identifier
//		-string: Language primary name 
//	-func(): Previous Page
//	-func(): Page to go to after selection
func setChooseDesiresPage_AddLanguage(window fyne.Window, submitFunction func(int, string)error, previousPage func(), nextPage func()){

	currentPage := func(){setChooseDesiresPage_AddLanguage(window, submitFunction, previousPage, nextPage)}

	title := getPageTitleCentered("My Mate Desires - Mental")

	backButton := getBackButtonCentered(previousPage)

	subtitle := getPageSubtitleCentered("Choose Language")

	worldLanguageObjectsList, err := worldLanguages.GetWorldLanguageObjectsList()
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	// This list stores the translated language names
	worldLanguageDescriptionsList := make([]string, 0, len(worldLanguageObjectsList))

	// This map will store all of the language names
	// If a language has multiple names, the first name is used
	//Map Structure: Language Description -> Language Object
	worldLanguageObjectsMap := make(map[string]worldLanguages.LanguageObject)

	for _, languageObject := range worldLanguageObjectsList{

		languageNamesList := languageObject.NamesList

		languageDescription := helpers.TranslateAndJoinStringListItems(languageNamesList, "/")

		worldLanguageDescriptionsList = append(worldLanguageDescriptionsList, languageDescription)

		worldLanguageObjectsMap[languageDescription] = languageObject
	}

	helpers.SortStringListToUnicodeOrder(worldLanguageDescriptionsList)

	selectFunction := func(itemIndex int){

		languageDescription := worldLanguageDescriptionsList[itemIndex]

		languageObject, exists := worldLanguageObjectsMap[languageDescription]
		if (exists == false){
			setErrorEncounteredPage(window, errors.New("worldLanguageNamesMap missing languageDescription"), currentPage)
			return
		}

		languageIdentifier := languageObject.Identifier
		languagePrimaryName := languageObject.NamesList[0]

		err := submitFunction(languageIdentifier, languagePrimaryName)
		if (err != nil){
			setErrorEncounteredPage(window, err, currentPage)
			return
		}

		nextPage()
	}

	languagesWidgetList, err := getFyneWidgetListFromStringList(worldLanguageDescriptionsList, selectFunction)
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	header := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator())

	page := container.NewBorder(header, nil, nil, nil, languagesWidgetList)
	
	setPageContent(page, window)
}


func setChooseDesiresPage_GenderIdentity(window fyne.Window, previousPage func()){

	currentPage := func(){setChooseDesiresPage_GenderIdentity(window, previousPage)}

	title := getPageTitleCentered("My Mate Desires - Mental")

	backButton := getBackButtonCentered(previousPage)

	subtitle := getPageSubtitleCentered(translate("Gender Identity"))

	description1 := getLabelCentered("Choose the gender identities that you desire.")
	description2 := getLabelCentered("This refers to the gender a user identifies as.")
	description3 := getLabelCentered("For example, if you desire people who identify as Men, choose Man.")

	optionTitlesList := []string{translate("Man"), translate("Woman")}

	optionNamesMap := make(map[string][]string)

	optionNamesMap[translate("Man")] = []string{"Man"}
	optionNamesMap[translate("Woman")] = []string{"Woman"}

	desireEditor, err := getDesireEditor_Choice(window, currentPage, "GenderIdentity", optionTitlesList, optionNamesMap, true, true, 1)
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
			setViewMyMateDesireStatisticsPage(window, "Gender Identity", "GenderIdentity", true, "Donut", "GenderIdentity", currentPage)
		}))

	page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)

	setPageContent(page, window)
}



func setChooseDesiresPage_Pets(window fyne.Window, previousPage func()){

	currentPage := func(){setChooseDesiresPage_Pets(window, previousPage)}

	title := getPageTitleCentered("My Mate Desires - Mental")

	backButton := getBackButtonCentered(previousPage)

	subtitle := getPageSubtitleCentered(translate("Pets"))

	description := getLabelCentered("Choose your pet desires.")

	allPetsButton := widget.NewButton("All Pets", func(){
			setChooseDesiresPage_AllPets(window, currentPage)
		})

	dogsButton := widget.NewButton("Dogs", func(){
			setChooseDesiresPage_Dogs(window, currentPage)
		})
	catsButton := widget.NewButton("Cats", func(){
			setChooseDesiresPage_Cats(window, currentPage)
		})

	buttonsGrid := getContainerCentered(container.NewGridWithColumns(1, allPetsButton, dogsButton, catsButton))

	page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description, widget.NewSeparator(), buttonsGrid)

	setPageContent(page, window)
}


func setChooseDesiresPage_AllPets(window fyne.Window, previousPage func()){

	currentPage := func(){setChooseDesiresPage_AllPets(window, previousPage)}

	title := getPageTitleCentered(translate("My Mate Desires - Mental"))

	backButton := getBackButtonCentered(previousPage)

	subtitle := getPageSubtitleCentered(translate("All Pets"))

	description1 := getLabelCentered("Choose your pets rating desires.")
	description2 := getLabelCentered("Users describe how much they enjoy having pets from 1 to 10.")
	description3 := getLabelCentered("Choose the user responses that you desire.")
	description4 := getLabelCentered("1/10 = Strongly Dislike, 10/10 = Strongly Like.")

	optionTitlesList := []string{"1/10", "2/10", "3/10", "4/10", "5/10", "6/10", "7/10", "8/10", "9/10", "10/10"}

	optionNamesMap := map[string][]string{
		"1/10": []string{"1"},
		"2/10": []string{"2"},
		"3/10": []string{"3"},
		"4/10": []string{"4"},
		"5/10": []string{"5"},
		"6/10": []string{"6"},
		"7/10": []string{"7"},
		"8/10": []string{"8"},
		"9/10": []string{"9"},
		"10/10": []string{"10"},
	}	

	desireEditor, err := getDesireEditor_Choice(window, currentPage, "PetsRating", optionTitlesList, optionNamesMap, false, true, 5)
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
			setViewMyMateDesireStatisticsPage(window, "Pets Rating", "PetsRating", true, "Bar", "PetsRating", currentPage)
		}))

	page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
	
	setPageContent(page, window)
}

func setChooseDesiresPage_Dogs(window fyne.Window, previousPage func()){

	currentPage := func(){setChooseDesiresPage_Dogs(window, previousPage)}
	
	title := getPageTitleCentered(translate("My Mate Desires - Mental"))

	backButton := getBackButtonCentered(previousPage)

	subtitle := getPageSubtitleCentered(translate("Dogs"))

	description1 := getLabelCentered("Choose your dogs rating desires.")
	description2 := getLabelCentered("Users describe how much they enjoy having dogs from 1 to 10.")
	description3 := getLabelCentered("Choose the user responses that you desire.")
	description4 := getLabelCentered("1/10 = Strongly Dislike, 10/10 = Strongly Like.")

	optionTitlesList := []string{"1/10", "2/10", "3/10", "4/10", "5/10", "6/10", "7/10", "8/10", "9/10", "10/10"}

	optionNamesMap := map[string][]string{
		"1/10": []string{"1"},
		"2/10": []string{"2"},
		"3/10": []string{"3"},
		"4/10": []string{"4"},
		"5/10": []string{"5"},
		"6/10": []string{"6"},
		"7/10": []string{"7"},
		"8/10": []string{"8"},
		"9/10": []string{"9"},
		"10/10": []string{"10"},
	}	
	
	desireEditor, err := getDesireEditor_Choice(window, currentPage, "DogsRating", optionTitlesList, optionNamesMap, false, true, 5)
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
			setViewMyMateDesireStatisticsPage(window, "Dogs Rating", "DogsRating", true, "Bar", "DogsRating", currentPage)
		}))

	page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
	
	setPageContent(page, window)
}


func setChooseDesiresPage_Cats(window fyne.Window, previousPage func()){

	currentPage := func(){setChooseDesiresPage_Cats(window, previousPage)}

	title := getPageTitleCentered(translate("My Mate Desires - Mental"))

	backButton := getBackButtonCentered(previousPage)

	subtitle := getPageSubtitleCentered(translate("Cats"))

	description1 := getLabelCentered("Choose your cats rating desires.")
	description2 := getLabelCentered("Users describe how much they enjoy having cats from 1 to 10.")
	description3 := getLabelCentered("Choose the user responses that you desire.")
	description4 := getLabelCentered("1/10 = Strongly Dislike, 10/10 = Strongly Like.")

	optionTitlesList := []string{"1/10", "2/10", "3/10", "4/10", "5/10", "6/10", "7/10", "8/10", "9/10", "10/10"}

	optionNamesMap := make(map[string][]string)
	optionNamesMap["1/10"] = []string{"1"}
	optionNamesMap["2/10"] = []string{"2"}
	optionNamesMap["3/10"] = []string{"3"}
	optionNamesMap["4/10"] = []string{"4"}
	optionNamesMap["5/10"] = []string{"5"}
	optionNamesMap["6/10"] = []string{"6"}
	optionNamesMap["7/10"] = []string{"7"}
	optionNamesMap["8/10"] = []string{"8"}
	optionNamesMap["9/10"] = []string{"9"}
	optionNamesMap["10/10"] = []string{"10"}
	
	desireEditor, err := getDesireEditor_Choice(window, currentPage, "CatsRating", optionTitlesList, optionNamesMap, false, true, 5)
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
			setViewMyMateDesireStatisticsPage(window, "Cats Rating", "CatsRating", true, "Bar", "CatsRating", currentPage)
		}))

	page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
	
	setPageContent(page, window)
}



