package config

import (
	"encoding/hex"
	"fmt"
	"image/color"
	termutil2 "tuxpa.in/t/erm/app/darktile/termutil"
)

var defaultConfig = Config{
	Opacity: 1.0,
	Font: Font{
		Family:    "", // internally packed font will be loaded by default
		Size:      18.0,
		DPI:       72.0,
		Ligatures: true,
	},
}

var defaultTheme = Theme{
	Black:               "#1d1f21",
	Red:                 "#cc6666",
	Green:               "#b5bd68",
	Yellow:              "#f0c674",
	Blue:                "#81a2be",
	Magenta:             "#b294bb",
	Cyan:                "#8abeb7",
	White:               "#c5c8c6",
	BrightBlack:         "#666666",
	BrightRed:           "#d54e53",
	BrightGreen:         "#b9ca4a",
	BrightYellow:        "#e7c547",
	BrightBlue:          "#7aa6da",
	BrightMagenta:       "#c397d8",
	BrightCyan:          "#70c0b1",
	BrightWhite:         "#eaeaea",
	Background:          "#000000",
	Foreground:          "#c5c8c6",
	SelectionBackground: "#33aa33",
	SelectionForeground: "#ffffff",
	CursorForeground:    "#1d1f21",
	CursorBackground:    "#c5c8c6",
}

func DefaultConfig() *Config {
	copiedConf := defaultConfig
	return &copiedConf
}

func DefaultTheme(conf *Config) (*termutil2.Theme, error) {
	return loadThemeFromConf(conf, &defaultTheme)
}

func LoadTheme(conf *Config) (*termutil2.Theme, error) {

	themeConf, err := loadTheme("")
	if err != nil {
		return nil, err
	}

	return loadThemeFromConf(conf, themeConf)
}

func LoadThemeFromPath(conf *Config, path string) (*termutil2.Theme, error) {

	themeConf, err := loadTheme(path)
	if err != nil {
		return nil, err
	}

	return loadThemeFromConf(conf, themeConf)
}

func loadThemeFromConf(conf *Config, themeConf *Theme) (*termutil2.Theme, error) {

	factory := termutil2.NewThemeFactory()

	colours := map[termutil2.Colour]string{
		termutil2.ColourBlack:               themeConf.Black,
		termutil2.ColourRed:                 themeConf.Red,
		termutil2.ColourGreen:               themeConf.Green,
		termutil2.ColourYellow:              themeConf.Yellow,
		termutil2.ColourBlue:                themeConf.Blue,
		termutil2.ColourMagenta:             themeConf.Magenta,
		termutil2.ColourCyan:                themeConf.Cyan,
		termutil2.ColourWhite:               themeConf.White,
		termutil2.ColourBrightBlack:         themeConf.BrightBlack,
		termutil2.ColourBrightRed:           themeConf.BrightRed,
		termutil2.ColourBrightGreen:         themeConf.BrightGreen,
		termutil2.ColourBrightYellow:        themeConf.BrightYellow,
		termutil2.ColourBrightBlue:          themeConf.BrightBlue,
		termutil2.ColourBrightMagenta:       themeConf.BrightMagenta,
		termutil2.ColourBrightCyan:          themeConf.BrightCyan,
		termutil2.ColourBrightWhite:         themeConf.BrightWhite,
		termutil2.ColourBackground:          themeConf.Background,
		termutil2.ColourForeground:          themeConf.Foreground,
		termutil2.ColourSelectionBackground: themeConf.SelectionBackground,
		termutil2.ColourSelectionForeground: themeConf.SelectionForeground,
		termutil2.ColourCursorForeground:    themeConf.CursorForeground,
		termutil2.ColourCursorBackground:    themeConf.CursorBackground,
	}

	for key, colHex := range colours {
		col, err := colourFromHex(colHex, conf.Opacity)
		if err != nil {
			return nil, fmt.Errorf("invalid hex value '%s' in theme", colHex)
		}
		factory.WithColour(
			key,
			col,
		)
	}

	return factory.Build(), nil

}

func colourFromHex(hexadecimal string, opacity float64) (color.Color, error) {
	if len(hexadecimal) == 0 {
		return nil, fmt.Errorf("colour value cannot be empty")
	}
	if hexadecimal[0] != '#' || len(hexadecimal) != 7 {
		return nil, fmt.Errorf("colour values should start with '#' and contain an RGB value encoded in hex, for example #ffffff")
	}

	decoded, err := hex.DecodeString(hexadecimal[1:])
	if err != nil {
		return nil, err
	}

	return color.RGBA{
		R: decoded[0],
		G: decoded[1],
		B: decoded[2],
		A: uint8(opacity * 0xff),
	}, nil
}
