package gui

// themeGui.go contains code to generate a custom fyne theme

import "fyne.io/fyne/v2"
import "fyne.io/fyne/v2/theme"

import "seekia/internal/imagery"

import "image/color"
import "errors"


// We use this to define a custom fyne theme
type customTheme struct{
	themeName string
	defaultTheme fyne.Theme
}

func getCustomFyneTheme(themeName string)(fyne.Theme, error){

	getStandardThemeObject := func()(fyne.Theme, error){

		if (themeName == "Light" || themeName == "Love" || themeName == "Ocean"){
			result := theme.LightTheme()
			return result, nil
		}
		if (themeName == "Dark"){
			result := theme.DarkTheme()
			return result, nil
		}
		return nil, errors.New("getCustomFyneTheme called with invalid themeName: " + themeName)
	}

	standardThemeObject, err := getStandardThemeObject()
	if (err != nil){ return nil, err }

	newTheme := customTheme{
		themeName: themeName,
		defaultTheme: standardThemeObject,
	}

	return newTheme, nil
}


// This function is used to define our custom fyne themes
// It changes a few default colors, while leaving all other colors the same as the default theme
func (input customTheme)Color(colorName fyne.ThemeColorName, variant fyne.ThemeVariant)color.Color{

	//TODO: Make these colors better and create more themes

	themeName := input.themeName

	switch colorName{

		case theme.ColorNameForeground:{

			switch themeName{

				case "Light", "Love", "Ocean":{

					newColor := color.Black
					return newColor
				}
				case "Dark":{

					newColor := color.White
					return newColor
				}
			}
		}
		case theme.ColorNameSeparator:{

			// This is the color used for separators

			switch themeName{

				case "Light":{
					newColor, err := imagery.GetColorObjectFromColorCode("b3b3b3")
					if (err == nil){
						return newColor
					}
				}
				case "Ocean":{
					newColor, err := imagery.GetColorObjectFromColorCode("646464")
					if (err == nil){
						return newColor
					}
				}
				default:{

					newColor, err := imagery.GetColorObjectFromColorCode("999999")
					if (err == nil){
						return newColor
					}
				}
			}
		}
		case theme.ColorNameInputBackground:{

			// This color is used for the background of input elements such as text entries

			switch themeName{

				case "Light":{

					newColor, err := imagery.GetColorObjectFromColorCode("b3b3b3")
					if (err == nil){
						return newColor
					}
				}
				case "Love":{

					newColor, err := imagery.GetColorObjectFromColorCode("ffbbbe")
					if (err == nil){
						return newColor
					}
				}
				case "Ocean":{

					newColor, err := imagery.GetColorObjectFromColorCode("ccd1ef")
					if (err == nil){
						return newColor
					}
				}
				default:{

					newColor, err := imagery.GetColorObjectFromColorCode("999999")
					if (err == nil){
						return newColor
					}
				}
			}
		}
		case theme.ColorNameBackground:{

			// This is the color used for the app background

			switch themeName{

				case "Love":{

					newColor, err := imagery.GetColorObjectFromColorCode("ff7a80")
					if (err == nil){
						return newColor
					}
				}
				case "Ocean":{

					newColor, err := imagery.GetColorObjectFromColorCode("7f6fff")
					if (err == nil){
						return newColor
					}
				}
			}
		}
		case theme.ColorNameOverlayBackground:{

			// This is the color used for backgrounds of overlays like dialogs.

			switch themeName{

				case "Love":{

					newColor, err := imagery.GetColorObjectFromColorCode("ffabaf")
					if (err == nil){
						return newColor
					}
				}
				case "Ocean":{

					newColor, err := imagery.GetColorObjectFromColorCode("a59aff")
					if (err == nil){
						return newColor
					}
				}
			}
		}
		case theme.ColorNameButton:{

			// This is the color used for buttons

			switch themeName{

				case "Light":{
					newColor, err := imagery.GetColorObjectFromColorCode("d8d8d8")
					if (err == nil){
						return newColor
					}
				}
				case "Love":{
					newColor, err := imagery.GetColorObjectFromColorCode("7664ff")
					if (err == nil){
						return newColor
					}
				}
				case "Ocean":{

					newColor, err := imagery.GetColorObjectFromColorCode("ccd1ef")
					if (err == nil){
						return newColor
					}
				}
				case "Dark":{
					newColor, err := imagery.GetColorObjectFromColorCode("4d4d4d")
					if (err == nil){
						return newColor
					}
				}
			}
		}
		case theme.ColorNamePlaceHolder:{

			// This is the color used for text

			newColor, err := imagery.GetColorObjectFromColorCode("4d4d4d")
			if (err == nil){
				return newColor
			}
		}

		case theme.ColorNamePrimary:{

			// This color is used for high importance buttons

			switch themeName{

				case "Love", "Ocean":{

					newColor, err := imagery.GetColorObjectFromColorCode("1300a8")
					if (err == nil){
						return newColor
					}
				}
			}
		}
	}

	// We will use the default color for this theme
	return input.defaultTheme.Color(colorName, variant)
}

// Our custom themes change nothing about the default theme fonts
func (input customTheme)Font(style fyne.TextStyle)fyne.Resource{

	themeFont := input.defaultTheme.Font(style)

	return themeFont
}

// Our custom themes change nothing about the default theme icons
func (input customTheme)Icon(iconName fyne.ThemeIconName)fyne.Resource{

	themeIcon := input.defaultTheme.Icon(iconName)

	return themeIcon
}

func (input customTheme)Size(name fyne.ThemeSizeName)float32{

	themeSize := input.defaultTheme.Size(name)

	if (name == theme.SizeNameText){

		// After fyne v2.3.0, text labels are no longer the same height as buttons
		// We increase the text size so that a text label is the same height as a button
		// We need to increase text size because we are creating grids by creating multiple VBoxes, and connecting them with an HBox
		//
		// If we could create grids in a different way, we could avoid having to do this
		// Example: Create a new grid type: container.NewThinGrid?
		//		-The columns will only be as wide as the the widest element within them
		//		-We can add separators between each row (grid.ShowRowLines = true) or between columns (grid.ShowColumnLines = true)
		//		-We can add borders (grid.ShowTopBorder = true, grid.ShowBottomBorder = true, grid.ShowLeftBorder = true, grid.ShowRightBorder = true)

		// Using a different grid type is the solution we need to eventually use
		// Then, we can show the user an option to increase the text size globally, and all grids will still render correctly

		result := themeSize * 1.08

		return result
	}

	return themeSize
}


