package gui

// peerActionsGui.go implements pages to manage peer actions, such as blocking, liking, and hiding

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/desires/myMateDesires"
import "seekia/internal/encoding"
import "seekia/internal/helpers"
import "seekia/internal/identity"
import "seekia/internal/messaging/myChatFilters"
import "seekia/internal/messaging/myChatMessages"
import "seekia/internal/myBlockedUsers"
import "seekia/internal/myContacts"
import "seekia/internal/myIdentity"
import "seekia/internal/myIgnoredUsers"
import "seekia/internal/myLikedUsers"
import "seekia/internal/myMatches"
import "seekia/internal/mySettings"
import "seekia/internal/network/appNetworkType/getAppNetworkType"
import "seekia/internal/profiles/myLocalProfiles"
import "seekia/internal/profiles/myProfileStatus"
import "seekia/internal/profiles/viewableProfiles"

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


func setViewPeerActionsPage(window fyne.Window, userIdentityHash [16]byte, previousPage func()){
	
	currentPage := func(){setViewPeerActionsPage(window, userIdentityHash, previousPage)}
	
	title := getPageTitleCentered("User Actions")

	backButton := getBackButtonCentered(previousPage)

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

	userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
	if (err != nil) {
		userIdentityHashHex := encoding.EncodeBytesToHexString(userIdentityHash[:])
		setErrorEncounteredPage(window, errors.New("setViewPeerActionsPage called with invalid userIdentityHash: " + userIdentityHashHex), previousPage)
		return
	}

	userIsBlocked, timeOfBlockingUnix, reasonExists, blockReason, err := myBlockedUsers.CheckIfUserIsBlocked(userIdentityHash)	
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	if (userIsBlocked == true){

		isBlockedText := getBoldLabelCentered("User Is Blocked")
		blockedAgoString, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeOfBlockingUnix, false)
		if (err != nil) {
			setErrorEncounteredPage(window, err, previousPage)
			return
		}

		blockedAgoLabel := getItalicLabelCentered("Blocked " + blockedAgoString + ".")

		page.Add(isBlockedText)
		page.Add(blockedAgoLabel)

		if (reasonExists == true){

			blockedReasonLabel := getBoldLabelCentered("Reason:")
			page.Add(blockedReasonLabel)

			blockReasonTrimmed, changesOccurred, err := helpers.TrimAndFlattenString(blockReason, 20)
			if (err != nil) {
				setErrorEncounteredPage(window, err, previousPage)
				return
			}
			if (changesOccurred == false){

				blockedReasonText := getLabelCentered(blockReason)

				page.Add(blockedReasonText)
			} else {

				blockedReasonText := widget.NewLabel(blockReasonTrimmed)

				viewReasonButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
						setViewTextPage(window, "Viewing Block Reason", blockReason, false, currentPage)
					})

				blockReasonRow := container.NewHBox(layout.NewSpacer(), blockedReasonText, viewReasonButton, layout.NewSpacer())

				page.Add(blockReasonRow)
			}
		}

		unblockButton := getWidgetCentered(widget.NewButton("Unblock User", func(){
				setConfirmUnblockUserPage(window, userIdentityHash, currentPage, currentPage)
			}))

		page.Add(unblockButton)
		page.Add(widget.NewSeparator())
	}

	if (userIsBlocked == false && userIdentityType == "Mate"){

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

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

				userIsLiked, _, err := myLikedUsers.CheckIfUserIsLiked(userIdentityHash)
				if (err != nil) { return nil, err }
				if (userIsLiked == true){
					unlikeIcon, err := getFyneImageIcon("Unlike")
					if (err != nil) { return nil, err }
					unlikeButton := widget.NewButton("Unlike", func(){
							setConfirmUnlikeUserPage(window, userIdentityHash, currentPage, currentPage)
						})

					unlikeButtonWithIcon := container.NewGridWithColumns(1, unlikeIcon, unlikeButton)
					return unlikeButtonWithIcon, nil
				}

				likeIcon, err := getFyneImageIcon("Like")
				if (err != nil) { return nil, err }
				likeButton := widget.NewButton("Like", func(){
						setConfirmLikeUserPage(window, userIdentityHash, currentPage, currentPage)
					})
		
				likeButtonWithIcon := container.NewGridWithColumns(1, likeIcon, likeButton)
				return likeButtonWithIcon, nil		
			}

			likeOrUnlikeButtonWithIcon, err := getLikeOrUnlikeButtonWithIcon()
			if (err != nil) { return nil, err }

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

				userIsIgnored, _, _, _, err := myIgnoredUsers.CheckIfUserIsIgnored(userIdentityHash)
				if (err != nil) { return nil, err }
				if (userIsIgnored == true){

					unignoreIcon := widget.NewIcon(theme.VisibilityIcon())
					
					unignoreButton := widget.NewButton("Unignore", func(){
							setConfirmUnignoreUserPage(window, userIdentityHash, currentPage, currentPage)
						})

					unignoreButtonWithIcon := container.NewGridWithColumns(1, unignoreIcon, unignoreButton)
					return unignoreButtonWithIcon, nil
				}

				ignoreIcon := widget.NewIcon(theme.VisibilityOffIcon())

				ignoreButton := widget.NewButton("Ignore", func(){
						setConfirmIgnoreUserPage(window, userIdentityHash, currentPage, currentPage)
					})

				ignoreButtonWithIcon := container.NewGridWithColumns(1, ignoreIcon, ignoreButton)
				return ignoreButtonWithIcon, nil		
			}
	
			ignoreOrUnignoreButtonWithIcon, err := getIgnoreOrUnignoreButtonWithIcon()
			if (err != nil) { return nil, err }

			greetIcon, err := getFyneImageIcon("Greet")
			if (err != nil) { return nil, err }
			greetButton := widget.NewButton("Greet", func(){
					setConfirmGreetOrRejectUserPage(window, "Greet", userIdentityHash, currentPage, currentPage)
				})
			greetButtonWithIcon := container.NewGridWithColumns(1, greetIcon, greetButton)

			rejectIcon, err := getFyneImageIcon("Reject")
			if (err != nil) { return nil, err } 
			rejectButton := widget.NewButton("Reject", func(){
					setConfirmGreetOrRejectUserPage(window, "Reject", userIdentityHash, currentPage, currentPage)
				})
			rejectButtonWithIcon := container.NewGridWithColumns(1, rejectIcon, rejectButton)
			
			buttonsWithIconsRow := getContainerCentered(container.NewGridWithRows(1, likeOrUnlikeButtonWithIcon, greetButtonWithIcon, ignoreOrUnignoreButtonWithIcon, rejectButtonWithIcon))

			return buttonsWithIconsRow, nil
		}

		buttonsWithIconsRow, err := getButtonsWithIconsRow()
		if (err != nil){
			setErrorEncounteredPage(window, err, previousPage)
			return
		}

		page.Add(buttonsWithIconsRow)
		page.Add(widget.NewSeparator())
	}

	buttonsGrid := container.NewGridWithColumns(1)

	if (userIsBlocked == false){

		contactExists, err := myContacts.CheckIfUserIsMyContact(userIdentityHash)
		if (err != nil) {
			setErrorEncounteredPage(window, err, previousPage)
			return
		}

		if (contactExists == true){

			manageContactButton := widget.NewButton("Manage Contact", func(){
					setManageContactPage(window, userIdentityHash, currentPage)
				})
			buttonsGrid.Add(manageContactButton)

		} else {

			addContactButton := widget.NewButtonWithIcon("Add Contact", theme.ContentAddIcon(), func(){
					setAddContactFromIdentityHashPage( window, userIdentityHash, currentPage, currentPage)
				})
			buttonsGrid.Add(addContactButton)
		}
	
		blockButton := widget.NewButtonWithIcon("Block", theme.CancelIcon(), func(){
				setConfirmBlockUserButton(window, userIdentityHash, currentPage, currentPage)
			})
		buttonsGrid.Add(blockButton)

		if (userIdentityType != "Host"){
			chatButton := widget.NewButtonWithIcon("Chat", theme.MailComposeIcon(), func(){
					setViewAConversationPage(window, userIdentityHash, true, currentPage)
				})
			buttonsGrid.Add(chatButton)
		}
	}

	viewProfileButton := widget.NewButtonWithIcon("View Profile", theme.VisibilityIcon(), func(){
			setViewPeerProfilePageFromIdentityHash(window, userIdentityHash, currentPage)
		})
	buttonsGrid.Add(viewProfileButton)

	viewIdentityHashButton := widget.NewButtonWithIcon("View Identity Hash", theme.VisibilityIcon(), func(){
			setViewIdentityHashPage(window, userIdentityHash, currentPage)
		})
	buttonsGrid.Add(viewIdentityHashButton)
	
	buttonsGridCentered := getContainerCentered(buttonsGrid)
	
	page.Add(buttonsGridCentered)

	setPageContent(page, window)
}


func setConfirmBlockUserButton(window fyne.Window, userIdentityHash [16]byte, previousPage func(), nextPage func()){

	setLoadingScreen(window, "Block User", "Loading Block User page...")

	title := getPageTitleCentered("Confirm Block User")

	backButton := getBackButtonCentered(previousPage)

	description1 := getBoldLabelCentered("Block this user?")
	description2 := getLabelCentered("The user will not be notified.")
	description3 := getLabelCentered("To notify the user, you must Reject them first.")
	
	page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator())

	getTotalNumberOfConversationMessages := func()(int, error){

		// We see how many messages exist on both network types.

		numberOfConversationMessages_Network1, err := myChatMessages.GetNumberOfMyConversationMessages(userIdentityHash, 1)
		if (err != nil) { return 0, err }

		numberOfConversationMessages_Network2, err := myChatMessages.GetNumberOfMyConversationMessages(userIdentityHash, 2)
		if (err != nil) { return 0, err }

		result := numberOfConversationMessages_Network1 + numberOfConversationMessages_Network2

		return result, nil
	}

	numberOfConversationMessages, err := getTotalNumberOfConversationMessages()
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (numberOfConversationMessages != 0){

		numberOfConversationMessagesString := helpers.ConvertIntToString(numberOfConversationMessages)

		description4 := getLabelCentered("This will delete your conversation history.")
		description5 := getBoldLabelCentered("You have " + numberOfConversationMessagesString + " conversation messages.")

		page.Add(description4)
		page.Add(description5)
		page.Add(widget.NewSeparator())
	}
	
	enterReasonText := getLabelCentered("Enter reason (optional):")
	page.Add(enterReasonText)

	enterReasonDescriptionA := getLabelCentered("This reason is stored privately and is not shared.")
	enterReasonDescriptionB := getLabelCentered("It can help you remember why you blocked a user.")

	enterReasonDescriptions := container.NewVBox(enterReasonDescriptionA, enterReasonDescriptionB)

	enterReasonTextEntry := widget.NewEntry()
	enterReasonTextEntry.SetPlaceHolder("Enter reason.")

	enterReasonEntryBoxed := getWidgetBoxed(enterReasonTextEntry)
	
	enterReasonEntryWithDescriptions := getContainerCentered(container.NewGridWithColumns(1, enterReasonDescriptions, enterReasonEntryBoxed))

	page.Add(enterReasonEntryWithDescriptions)
	page.Add(widget.NewSeparator())

	blockUserFunction := func()error{

		reason := enterReasonTextEntry.Text
		if (reason == ""){
			err := myBlockedUsers.BlockUser(userIdentityHash, false, "")
			if (err != nil) { return err }
		} else {
			err := myBlockedUsers.BlockUser(userIdentityHash, true, reason)
			if (err != nil) { return err }
		}

		userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
		if (err != nil) { return err }

		if (userIdentityType != "Host"){

			//TODO: Add delete peer chat keys, secret inboxes, and device identifier

			err = myChatMessages.DeleteAllPeerConversationMessages(userIdentityHash)
			if (err != nil) { return err }

			err := mySettings.SetSetting(userIdentityType + "ChatConversationsGeneratedStatus", "No")
			if (err != nil) { return err }
		}

		if (userIdentityType == "Mate"){	

			appNetworkType, err := getAppNetworkType.GetAppNetworkType()
			if (err != nil) { return err }

			myMatchesReady, myMatchesList, err := myMatches.GetMyMatchesList(appNetworkType)
			if (err != nil) { return err }
			if (myMatchesReady == false){
				err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
				if (err != nil) { return err }
			} else {
				userIsAMatch := slices.Contains(myMatchesList, userIdentityHash)
				if (userIsAMatch == true){
					err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
					if (err != nil) { return err }
				}
			}
		}

		return nil
	}

	confirmButton := getWidgetCentered(widget.NewButtonWithIcon("Block User", theme.ConfirmIcon(), func(){

		setLoadingScreen(window, "Block User", "Blocking User...")
		err := blockUserFunction()
		if (err != nil){
			setErrorEncounteredPage(window, err, previousPage)
			return
		}

		nextPage()
	}))

	page.Add(confirmButton)

	setPageContent(page, window)
}


func setConfirmUnblockUserPage(window fyne.Window, userIdentityHash [16]byte, previousPage func(), nextPage func()){

	setLoadingScreen(window, "Unblock User", "Loading Unblock User page...")

	currentPage := func(){setConfirmUnblockUserPage(window, userIdentityHash, previousPage, nextPage)}

	title := getPageTitleCentered("Confirm Unblock User")
	
	backButton := getBackButtonCentered(previousPage)

	description1 := getBoldLabelCentered("Unblock this user?")
	description2 := getLabelCentered("They will not be notified.")

	userIsBlocked, timeOfBlockingUnix, reasonExists, blockReason, err := myBlockedUsers.CheckIfUserIsBlocked(userIdentityHash)	
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (userIsBlocked == false){
		setErrorEncounteredPage(window, errors.New("setConfirmUnblockUserPage visited when user is not blocked."), previousPage)
		return
	}

	blockedAgoString, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeOfBlockingUnix, false)
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	blockedAgoTimeLabel := getItalicLabelCentered("Blocked " + blockedAgoString + ".")

	page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, blockedAgoTimeLabel)

	if (reasonExists == true){

		page.Add(widget.NewSeparator())

		blockReasonText := getLabelCentered("Reason for blocking:")
		page.Add(blockReasonText)

		blockReasonTrimmed, changesOccurred, err := helpers.TrimAndFlattenString(blockReason, 20)
		if (err != nil) {
			setErrorEncounteredPage(window, err, previousPage)
			return
		}
		if (changesOccurred == false){

			blockedReasonText := getBoldLabelCentered(blockReason)

			page.Add(blockedReasonText)
		} else {

			blockedReasonText := getBoldLabel(blockReasonTrimmed)

			viewReasonButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
					setViewTextPage(window, "Viewing Block Reason", blockReason, false, currentPage)
				})

			blockReasonRow := container.NewHBox(layout.NewSpacer(), blockedReasonText, viewReasonButton, layout.NewSpacer())

			page.Add(blockReasonRow)
		}

		page.Add(widget.NewSeparator())
	}

	unblockUserFunction := func()error{

		err := myBlockedUsers.UnblockUser(userIdentityHash)
		if (err != nil) { return err }

		userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
		if (err != nil) { return err }

		if (userIdentityType != "Host"){

			// If the blocked user sent us any messages, then there may be new messages available
			// These are messages that we would have skipped when the sender was blocked

			err := mySettings.SetSetting(userIdentityType + "ChatConversationsNeedRefreshYesNo", "Yes")
			if (err != nil) { return err }
		}

		if (userIdentityType == "Mate"){

			// Now we check if the user would have been a match if they were not blocked
			// If yes, we know that matches need to be refreshed

			appNetworkType, err := getAppNetworkType.GetAppNetworkType()
			if (err != nil) { return err }

			profileExists, _, getAnyUserAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(userIdentityHash, appNetworkType, true, false, false)
			if (err != nil) { return err }
			if (profileExists == true) {

				passesMyDesires, err := myMateDesires.CheckIfMateProfilePassesAllMyDesires(false, "", getAnyUserAttributeFunction)
				if (err != nil) { return err }
				if (passesMyDesires == true){
					err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
					if (err != nil) { return err }
				}
			}
		}

		return nil
	}

	confirmButton := getWidgetCentered(widget.NewButtonWithIcon("Unblock User", theme.ConfirmIcon(), func(){

		setLoadingScreen(window, "Unblock User", "Unblocking User...")
		err := unblockUserFunction()
		if (err != nil){
			setErrorEncounteredPage(window, err, previousPage)
			return
		}
		
		nextPage()
	}))

	page.Add(confirmButton)

	setPageContent(page, window)
}


func setConfirmIgnoreUserPage(window fyne.Window, userIdentityHash [16]byte, previousPage func(), nextPage func()){

	userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	if (userIdentityType != "Mate"){
		setErrorEncounteredPage(window, errors.New("Trying to ignore non-mate user."), previousPage)
		return
	}

	title := getPageTitleCentered("Confirm Ignore User")

	backButton := getBackButtonCentered(previousPage)

	description1 := getBoldLabelCentered("Ignore user?")
	description2 := getLabelCentered("The user will not show up in your matches/chat conversations.")
	description3 := getLabelCentered("You can change this by enabling Show Ignored Users in your desires/chat filters.")
	description4 := getLabelCentered("The user will not be notified.")
	description5 := getLabelCentered("To notify them, Reject them first.")

	enterReasonText := getBoldLabelCentered("Enter reason (optional):")

	enterReasonDescriptionA := getLabelCentered("This reason is stored privately and is not shared.")
	enterReasonDescriptionB := getLabelCentered("It can help you remember why you hid a user.")

	enterReasonDescriptions := container.NewVBox(enterReasonDescriptionA, enterReasonDescriptionB)

	enterReasonTextEntry := widget.NewEntry()
	enterReasonTextEntry.SetPlaceHolder("Enter reason.")

	enterReasonEntryBoxed := getWidgetBoxed(enterReasonTextEntry)
	
	enterReasonEntryWithDescriptions := getContainerCentered(container.NewGridWithColumns(1, enterReasonDescriptions, enterReasonEntryBoxed))

	ignoreUserFunction := func()error{

		reason := enterReasonTextEntry.Text
		if (reason == ""){
			err := myIgnoredUsers.IgnoreUser(userIdentityHash, false, "")
			if (err != nil) { return err }
		} else {
			err := myIgnoredUsers.IgnoreUser(userIdentityHash, true, reason)
			if (err != nil) { return err }
		}


		hideIgnoredUsersBool, err := myChatFilters.GetChatFilterOnOffStatus("Mate", "HideIgnoredUsers")
		if (err != nil) { return err }
		if (hideIgnoredUsersBool == true){

			err := mySettings.SetSetting("MateChatConversationsNeedRefreshYesNo", "Yes")
			if (err != nil) { return err }
		}

		getShowIgnoredMatchesBool := func()(bool, error){

			//TODO
			return false, nil
		}

		showIgnoredMatchesBool, err := getShowIgnoredMatchesBool()
		if (err != nil) { return err }

		if (showIgnoredMatchesBool == false){

			appNetworkType, err := getAppNetworkType.GetAppNetworkType()
			if (err != nil) { return err }

			myMatchesReady, myMatchesList, err := myMatches.GetMyMatchesList(appNetworkType)
			if (err != nil) { return err }
			if (myMatchesReady == false){
				err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
				if (err != nil) { return err }
			} else {
				userIsAMatch := slices.Contains(myMatchesList, userIdentityHash)
				if (userIsAMatch == true){
					err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
					if (err != nil) { return err }
				}
			}
		}

		return nil
	}

	confirmButton := getWidgetCentered(widget.NewButtonWithIcon("Ignore User", theme.ConfirmIcon(), func(){

		setLoadingScreen(window, "Ignore User", "Hiding User...")
		err := ignoreUserFunction()
		if (err != nil){
			setErrorEncounteredPage(window, err, previousPage)
			return
		}
		
		nextPage()
	}))
	
	page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, description5, widget.NewSeparator(), enterReasonText, enterReasonEntryWithDescriptions, widget.NewSeparator(), confirmButton)

	setPageContent(page, window)
}


func setConfirmUnignoreUserPage(window fyne.Window, userIdentityHash [16]byte, previousPage func(), nextPage func()){

	userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (userIdentityType != "Mate"){
		setErrorEncounteredPage(window, errors.New("setConfirmUnignoreUserPage called with non-mate user."), previousPage)
		return
	}

	setLoadingScreen(window, "Unignore User", "Loading Unignore User page...")

	currentPage := func(){setConfirmUnignoreUserPage(window, userIdentityHash, previousPage, nextPage)}

	title := getPageTitleCentered("Confirm Unignore User")
	
	backButton := getBackButtonCentered(previousPage)

	description1 := getBoldLabelCentered("Unignore this user?")
	description2 := getLabelCentered("They will not be notified.")

	userIsIgnored, timeOfHidingUnix, reasonExists, ignoreReason, err := myIgnoredUsers.CheckIfUserIsIgnored(userIdentityHash)	
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (userIsIgnored == false){
		setErrorEncounteredPage(window, errors.New("setConfirmUnignoreUserPage visited when user is not ignored."), previousPage)
		return
	}

	ignoredAgoString, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeOfHidingUnix, false)
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	ignoredAgoTimeLabel := getItalicLabelCentered("Ignored " + ignoredAgoString + ".")

	page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, ignoredAgoTimeLabel)	
	
	if (reasonExists == true){

		page.Add(widget.NewSeparator())

		ignoreReasonText := getLabelCentered("Reason for hiding:")
		page.Add(ignoreReasonText)

		ignoreReasonTrimmed, changesOccurred, err := helpers.TrimAndFlattenString(ignoreReason, 20)
		if (err != nil) {
			setErrorEncounteredPage(window, err, previousPage)
			return
		}
		if (changesOccurred == false){

			ignoreReasonText := getBoldLabelCentered(ignoreReason)

			page.Add(ignoreReasonText)
		} else {

			ignoreReasonText := getBoldLabel(ignoreReasonTrimmed)

			viewReasonButton := widget.NewButtonWithIcon("", theme.VisibilityIcon(), func(){
					setViewTextPage(window, "Viewing Ignore Reason", ignoreReason, false, currentPage)
				})

			ignoreReasonRow := container.NewHBox(layout.NewSpacer(), ignoreReasonText, viewReasonButton, layout.NewSpacer())

			page.Add(ignoreReasonRow)
		}

		page.Add(widget.NewSeparator())
	}

	unignoreUserFunction := func()error{

		err := myIgnoredUsers.UnignoreUser(userIdentityHash)
		if (err != nil) { return err }

		hideIgnoredUsersBool, err := myChatFilters.GetChatFilterOnOffStatus("Mate", "HideIgnoredUsers")
		if (err != nil) { return err }
		if (hideIgnoredUsersBool == true){

			err := mySettings.SetSetting("MateChatConversationsNeedRefreshYesNo", "Yes")
			if (err != nil) { return err }
		}

		getShowIgnoredMatchesBool := func()(bool, error){

			//TODO

			return false, nil
		}

		showIgnoredMatchesBool, err := getShowIgnoredMatchesBool()
		if (err != nil) { return err }
		if (showIgnoredMatchesBool == false){

			// Now we check if user would have been a match if they were not ignored
			// If yes, matches need to be refreshed

			appNetworkType, err := getAppNetworkType.GetAppNetworkType()
			if (err != nil) { return err }

			profileExists, _, getAnyUserAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(userIdentityHash, appNetworkType, true, false, false)
			if (err != nil) { return err }
			if (profileExists == true) {

				passesMyDesires, err := myMateDesires.CheckIfMateProfilePassesAllMyDesires(false, "", getAnyUserAttributeFunction)
				if (err != nil) { return err }

				if (passesMyDesires == true){
					err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
					if (err != nil) { return err }
				}
			}
		}

		return nil
	}

	confirmButton := getWidgetCentered(widget.NewButtonWithIcon("Unignore User", theme.ConfirmIcon(), func(){

		setLoadingScreen(window, "Unignore User", "Unhiding User...")
		err := unignoreUserFunction()
		if (err != nil){
			setErrorEncounteredPage(window, err, previousPage)
			return
		}
		
		nextPage()
	}))

	page.Add(confirmButton)

	setPageContent(page, window)
}


func setConfirmLikeUserPage(window fyne.Window, userIdentityHash [16]byte, previousPage func(), nextPage func()){

	userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
	if (err != nil) {
		userIdentityHashHex := encoding.EncodeBytesToHexString(userIdentityHash[:])
		setErrorEncounteredPage(window, errors.New("setConfirmLikeUserPage called with invalid identityHash: " + userIdentityHashHex), previousPage)
		return
	}
	if (userIdentityType != "Mate"){
		setErrorEncounteredPage(window, errors.New("setConfirmLikeUserPage called with non-mate identity."), previousPage)
		return
	}

	title := getPageTitleCentered("Confirm Like User")

	backButton := getBackButtonCentered(previousPage)

	description1 := getBoldLabelCentered("Like user?")
	description2 := getLabelCentered("The user will be saved in your liked users.")
	description3 := getLabelCentered("They will not be notified.")
	description4 := getLabelCentered("To notify them, Greet or message them.")

	likeUserFunction := func()error{

		err := myLikedUsers.LikeUser(userIdentityHash)
		if (err != nil) { return err }

		onlyShowLikedUsersBool, err := myChatFilters.GetChatFilterOnOffStatus("Mate", "OnlyShowLikedUsers")
		if (err != nil) { return err }
		if (onlyShowLikedUsersBool == true){

			err := mySettings.SetSetting("MateChatConversationsNeedRefreshYesNo", "Yes")
			if (err != nil) { return err }
		}

		getOnlyShowLikedMatchesBool := func()(bool, error){

			exists, onlyShowLikedMatches, err := myLocalDesires.GetDesire("OnlyShowLikedMatches")
			if (err != nil) { return false, err }
			if (exists == true && onlyShowLikedMatches == "Yes"){
				return true, nil
			}
			return false, nil
		}

		onlyShowLikedMatchesBool, err := getOnlyShowLikedMatchesBool()
		if (err != nil) { return err }

		if (onlyShowLikedMatchesBool == true){

			// Now we check if user is now a match, now that they are liked
			// If yes, matches need to be refreshed

			appNetworkType, err := getAppNetworkType.GetAppNetworkType()
			if (err != nil) { return err }

			profileExists, _, getAnyUserAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(userIdentityHash, appNetworkType, true, false, false)
			if (err != nil) { return err }
			if (profileExists == true) {

				passesMyDesires, err := myMateDesires.CheckIfMateProfilePassesAllMyDesires(false, "", getAnyUserAttributeFunction)
				if (err != nil) { return err }

				if (passesMyDesires == true){
					err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
					if (err != nil) { return err }
				}
			}
		}

		return nil
	}

	confirmButton := getWidgetCentered(widget.NewButtonWithIcon("Like User", theme.ConfirmIcon(), func(){

			setLoadingScreen(window, "Like User", "Like User...")
			err := likeUserFunction()
			if (err != nil){
				setErrorEncounteredPage(window, err, previousPage)
				return
			}

			nextPage()
		}))

	page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), confirmButton)

	setPageContent(page, window)
}

func setConfirmUnlikeUserPage(window fyne.Window, userIdentityHash [16]byte, previousPage func(), nextPage func()){

	userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (userIdentityType != "Mate"){
		setErrorEncounteredPage(window, errors.New("setConfirmUnlikeUserPage called with non-mate identity."), previousPage)
		return
	}

	setLoadingScreen(window, "Unlike User", "Loading Unlike User page...")

	title := getPageTitleCentered("Confirm Unlike User")

	backButton := getBackButtonCentered(previousPage)

	description1 := getBoldLabelCentered("Unlike user?")
	description2 := getLabelCentered("The user will be removed from your likes.")
	description3 := getLabelCentered("They will not be notified.")

	userIsLiked, timeOfLikingUnix, err := myLikedUsers.CheckIfUserIsLiked(userIdentityHash)	
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (userIsLiked == false){
		setErrorEncounteredPage(window, errors.New("setConfirmUnlikeUserPage visited when user is not liked."), previousPage)
		return
	}

	likedAgoString, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeOfLikingUnix, false)
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	likedAgoLabel := getItalicLabelCentered("Liked " + likedAgoString + ".")

	unlikeUserFunction := func()error{

		err := myLikedUsers.UnlikeUser(userIdentityHash)
		if (err != nil) { return err }

		onlyShowLikedUsersBool, err := myChatFilters.GetChatFilterOnOffStatus("Mate", "OnlyShowLikedUsers")
		if (err != nil) { return err }
		if (onlyShowLikedUsersBool == true){

			err := mySettings.SetSetting("MateChatConversationsNeedRefreshYesNo", "Yes")
			if (err != nil) { return err }
		}

		getOnlyShowLikedMatchesBool := func()(bool, error){

			exists, onlyShowLikedMatches, err := myLocalDesires.GetDesire("OnlyShowLikedMatches")
			if (err != nil) { return false, err }
			if (exists == true && onlyShowLikedMatches == "Yes"){
				return true, nil
			}
			return false, nil
		}

		onlyShowLikedMatchesBool, err := getOnlyShowLikedMatchesBool()
		if (err != nil) { return err }
		if (onlyShowLikedMatchesBool == true){

			// We see if the user will no longer be a match.
			// If so, we make sure that matchesNeedRefresh status is updated

			appNetworkType, err := getAppNetworkType.GetAppNetworkType()
			if (err != nil) { return err }

			myMatchesReady, myMatchesList, err := myMatches.GetMyMatchesList(appNetworkType)
			if (err != nil) { return err }
			if (myMatchesReady == false){
				err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
				if (err != nil) { return err }
			} else {
				userIsAMatch := slices.Contains(myMatchesList, userIdentityHash)
				if (userIsAMatch == true){
					err = mySettings.SetSetting("MatchesNeedRefreshYesNo", "Yes")
					if (err != nil) { return err }
				}
			}
		}

		return nil
	}

	confirmButton := getWidgetCentered(widget.NewButtonWithIcon("Unlike User", theme.ConfirmIcon(), func(){

			setLoadingScreen(window, "Unlike User", "Unliking User...")
			err := unlikeUserFunction()
			if (err != nil){
				setErrorEncounteredPage(window, err, previousPage)
				return
			}
			
			nextPage()
		}))

	page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, likedAgoLabel, confirmButton)

	setPageContent(page, window)
}

func setConfirmGreetOrRejectUserPage(window fyne.Window, greetOrReject string, userIdentityHash [16]byte, previousPage func(), afterSendPage func()){

	currentPage := func(){setConfirmGreetOrRejectUserPage(window, greetOrReject, userIdentityHash, previousPage, afterSendPage)}

	if (greetOrReject != "Greet" && greetOrReject != "Reject"){
		setErrorEncounteredPage(window, errors.New("setConfirmGreetOrRejectUserPage called with invalid greetOrReject: " + greetOrReject), previousPage)
		return
	}
	
	userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (userIdentityType != "Mate"){
		setErrorEncounteredPage(window, errors.New("Trying to greet/reject a non-mate user."), previousPage)
		return
	}

	title := getPageTitleCentered("Confirm " + greetOrReject + " User")

	backButton := getBackButtonCentered(previousPage)

	greetOrRejectLowercase := strings.ToLower(greetOrReject)
	
	myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Mate")
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (myIdentityExists == false){

		description1 := getBoldLabelCentered("Your Mate identity does not exist.")
		description2 := getLabelCentered("A " + greetOrRejectLowercase + " is a message sent to another user.")
		description3 := getLabelCentered("You cannot " + greetOrRejectLowercase + " a user without a mate identity.")
		description4 := getLabelCentered("Create your Mate identity?")

		createIdentityButton := getWidgetCentered(widget.NewButtonWithIcon("Create Mate Identity", theme.NavigateNextIcon(), func(){
				setChooseNewIdentityHashPage(window, "Mate", currentPage, currentPage)
			}))

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

	exists, iAmDisabled, err := myLocalProfiles.GetProfileData("Mate", "Disabled")
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}
	if (exists == true && iAmDisabled == "Yes"){
		description1 := getBoldLabelCentered("Your Mate profile is disabled.")
		description2 := getLabelCentered("A " + greetOrRejectLowercase + " is a message sent to another user.")
		description3 := getLabelCentered("You cannot " + greetOrRejectLowercase + " users with a disabled profile.")
		description4 := getLabelCentered("Enable your profile on the Broadcast page to continue.")

		visitBroadcastPageButton := getWidgetCentered(widget.NewButtonWithIcon("Visit Broadcast Page", theme.NavigateNextIcon(), func(){
				setBroadcastPage(window, "Mate", currentPage)
			}))
		
		page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, visitBroadcastPageButton)
		
		setPageContent(page, window)
		return
	}

	appNetworkType, err := getAppNetworkType.GetAppNetworkType()
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage)
		return
	}

	myIdentityFound, myProfileIsActiveStatus, err := myProfileStatus.GetMyProfileIsActiveStatus(myIdentityHash, appNetworkType)
	if (err != nil) {
		setErrorEncounteredPage(window, err, previousPage) 
		return
	}
	if (myIdentityFound == false) {
		setErrorEncounteredPage(window, errors.New("My identity not found after being found already."), previousPage) 
		return 
	}
	if (myProfileIsActiveStatus == false){
	
		description1 := getBoldLabelCentered("Your Mate profile is not active.")
		description2 := getLabelCentered("A " + greetOrRejectLowercase + " is a message sent to another user.")
		description3 := getLabelCentered("You must broadcast your Mate profile to " + greetOrRejectLowercase + " users.")
		description4 := getLabelCentered("Broadcast your Mate profile on the Broadcast page.")

		broadcastPageButton := getWidgetCentered(widget.NewButtonWithIcon("Visit Broadcast Page", theme.NavigateNextIcon(), func(){
				setBroadcastPage(window, "Mate", currentPage)
			}))
		
		page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, broadcastPageButton)
		setPageContent(page, window)
		return
	}

	description1 := getBoldLabelCentered(greetOrReject + " User?")

	description2 := getLabelCentered("This will send the user a " + greetOrReject + " message.")

	getDescription3Text := func()string{

		if (greetOrReject == "Greet"){
			result := translate("This is a way of signaling interest in the user.")

			return result
		}
		// greetOrReject = "Reject"

		result := translate("This is a way of telling users you are not interested in them.")

		return result
	}

	description3Text := getDescription3Text()

	description3Label := widget.NewLabel(description3Text)

	helpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
			setGreetAndRejectExplainerPage(window, currentPage)
		})
	description3Row := container.NewHBox(layout.NewSpacer(), description3Label, helpButton, layout.NewSpacer())

	description4 := getLabelCentered("You will pay for the message on the next page.")

	page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3Row, description4, widget.NewSeparator())

	//Outputs:
	//	-bool: Section is needed
	//	-*fyne.Container: Greet or reject status section
	//	-error
	getCurrentGreetOrRejectStatusSection := func()(bool, *fyne.Container, error){

		myIdentityFound, conversationFound, _, _, iHaveContactedThem, iHaveRejectedThem, timeOfMyMostRecentGreetOrReject, theyHaveContactedMe, theyHaveRejectedMe, timeOfTheirMostRecentGreetOrReject, err := myChatMessages.GetMyConversationInfoAndSortedMessagesList(myIdentityHash, userIdentityHash, appNetworkType)
		if (err != nil) { return false, nil, err }
		if (myIdentityFound == false){
			return false, nil, errors.New("My identity not found after being found already.")
		}
		if (conversationFound == false){
			return false, nil, nil		
		}
		if (iHaveContactedThem == false && theyHaveContactedMe == false){
			return false, nil, nil
		}

		statusSection := container.NewVBox()
		if (iHaveContactedThem == true){

			timeAgoText, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeOfMyMostRecentGreetOrReject, false)
			if (err != nil) { return false, nil, err }

			if (iHaveRejectedThem == true){
				greetOrRejectStatus := getBoldLabelCentered("You rejected this user " + timeAgoText + ".")
				statusSection.Add(greetOrRejectStatus)
			} else {
				greetOrRejectStatus := getBoldLabelCentered("You greeted this user " + timeAgoText + ".")
				statusSection.Add(greetOrRejectStatus)
			}
		}
		if (theyHaveContactedMe == true){
			timeAgoText, err := helpers.ConvertUnixTimeToTimeAgoTranslated(timeOfTheirMostRecentGreetOrReject, false)
			if (err != nil) { return false, nil, err }

			if (theyHaveRejectedMe == true){
				greetOrRejectStatus := getBoldLabelCentered("This user rejected you " + timeAgoText + ".")
				statusSection.Add(greetOrRejectStatus)
			} else {
				greetOrRejectStatus := getBoldLabelCentered("This user greeted you " + timeAgoText + ".")
				statusSection.Add(greetOrRejectStatus)
			}
		}
		
		return true, statusSection, nil
	}

	greetOrRejectStatusSectionNeeded, greetOrRejectStatusSection, err := getCurrentGreetOrRejectStatusSection()
	if (err != nil){
		setErrorEncounteredPage(window, err, previousPage) 
		return
	}

	if (greetOrRejectStatusSectionNeeded == true){
		page.Add(greetOrRejectStatusSection)
	}

	greetOrRejectButton := getWidgetCentered(widget.NewButtonWithIcon(greetOrReject, theme.ConfirmIcon(), func(){

			getMessageCommunication := func()string{

				if (greetOrReject == "Greet"){
					return ">!>Greet"
				}
				return ">!>Reject"
			}

			messageCommunication := getMessageCommunication()

			setFundAndSendChatMessagePage(window, myIdentityHash, userIdentityHash, messageCommunication, false, currentPage, afterSendPage)
		}))

	page.Add(greetOrRejectButton)

	setPageContent(page, window)
}


