// Package font provides embedded font resources for hdmistat
package font

import (
	_ "embed"
	"fmt"

	"github.com/golang/freetype/truetype"
)

// IBM Plex Mono fonts
//
//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-Thin.ttf
var ibmPlexMonoThin []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-ThinItalic.ttf
var ibmPlexMonoThinItalic []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-ExtraLight.ttf
var ibmPlexMonoExtraLight []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-ExtraLightItalic.ttf
var ibmPlexMonoExtraLightItalic []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-Light.ttf
var ibmPlexMonoLight []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-LightItalic.ttf
var ibmPlexMonoLightItalic []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-Regular.ttf
var ibmPlexMonoRegular []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-Italic.ttf
var ibmPlexMonoItalic []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-Medium.ttf
var ibmPlexMonoMedium []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-MediumItalic.ttf
var ibmPlexMonoMediumItalic []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-SemiBold.ttf
var ibmPlexMonoSemiBold []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-SemiBoldItalic.ttf
var ibmPlexMonoSemiBoldItalic []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-Bold.ttf
var ibmPlexMonoBold []byte

//go:embed fonts/IBM_Plex_Mono/IBMPlexMono-BoldItalic.ttf
var ibmPlexMonoBoldItalic []byte

// Source Code Pro fonts
//
//go:embed fonts/Source_Code_Pro/SourceCodePro-ExtraLight.ttf
var sourceCodeProExtraLight []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-ExtraLightItalic.ttf
var sourceCodeProExtraLightItalic []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-Light.ttf
var sourceCodeProLight []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-LightItalic.ttf
var sourceCodeProLightItalic []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-Regular.ttf
var sourceCodeProRegular []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-Italic.ttf
var sourceCodeProItalic []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-Medium.ttf
var sourceCodeProMedium []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-MediumItalic.ttf
var sourceCodeProMediumItalic []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-SemiBold.ttf
var sourceCodeProSemiBold []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-SemiBoldItalic.ttf
var sourceCodeProSemiBoldItalic []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-Bold.ttf
var sourceCodeProBold []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-BoldItalic.ttf
var sourceCodeProBoldItalic []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-ExtraBold.ttf
var sourceCodeProExtraBold []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-ExtraBoldItalic.ttf
var sourceCodeProExtraBoldItalic []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-Black.ttf
var sourceCodeProBlack []byte

//go:embed fonts/Source_Code_Pro/SourceCodePro-BlackItalic.ttf
var sourceCodeProBlackItalic []byte

// FontWeight represents font weight
type FontWeight string

// Font weight constants
const (
	// WeightThin represents thin font weight
	WeightThin       FontWeight = "thin"
	WeightExtraLight FontWeight = "extralight"
	WeightLight      FontWeight = "light"
	WeightRegular    FontWeight = "regular"
	WeightMedium     FontWeight = "medium"
	WeightSemiBold   FontWeight = "semibold"
	WeightBold       FontWeight = "bold"
	WeightExtraBold  FontWeight = "extrabold"
	WeightBlack      FontWeight = "black"
)

// FontFamily represents a font family
type FontFamily string

// Font family constants
const (
	// FamilyIBMPlexMono represents IBM Plex Mono font family
	FamilyIBMPlexMono   FontFamily = "ibmplexmono"
	FamilySourceCodePro FontFamily = "sourcecodepro"
)

// LoadFont loads a font with the specified family, weight, and italic style
func LoadFont(family FontFamily, weight FontWeight, italic bool) (*truetype.Font, error) {
	var fontData []byte

	switch family {
	case FamilyIBMPlexMono:
		switch weight {
		case WeightThin:
			if italic {
				fontData = ibmPlexMonoThinItalic
			} else {
				fontData = ibmPlexMonoThin
			}
		case WeightExtraLight:
			if italic {
				fontData = ibmPlexMonoExtraLightItalic
			} else {
				fontData = ibmPlexMonoExtraLight
			}
		case WeightLight:
			if italic {
				fontData = ibmPlexMonoLightItalic
			} else {
				fontData = ibmPlexMonoLight
			}
		case WeightRegular:
			if italic {
				fontData = ibmPlexMonoItalic
			} else {
				fontData = ibmPlexMonoRegular
			}
		case WeightMedium:
			if italic {
				fontData = ibmPlexMonoMediumItalic
			} else {
				fontData = ibmPlexMonoMedium
			}
		case WeightSemiBold:
			if italic {
				fontData = ibmPlexMonoSemiBoldItalic
			} else {
				fontData = ibmPlexMonoSemiBold
			}
		case WeightBold:
			if italic {
				fontData = ibmPlexMonoBoldItalic
			} else {
				fontData = ibmPlexMonoBold
			}
		default:
			return nil, fmt.Errorf("unsupported weight %s for IBM Plex Mono", weight)
		}

	case FamilySourceCodePro:
		switch weight {
		case WeightExtraLight:
			if italic {
				fontData = sourceCodeProExtraLightItalic
			} else {
				fontData = sourceCodeProExtraLight
			}
		case WeightLight:
			if italic {
				fontData = sourceCodeProLightItalic
			} else {
				fontData = sourceCodeProLight
			}
		case WeightRegular:
			if italic {
				fontData = sourceCodeProItalic
			} else {
				fontData = sourceCodeProRegular
			}
		case WeightMedium:
			if italic {
				fontData = sourceCodeProMediumItalic
			} else {
				fontData = sourceCodeProMedium
			}
		case WeightSemiBold:
			if italic {
				fontData = sourceCodeProSemiBoldItalic
			} else {
				fontData = sourceCodeProSemiBold
			}
		case WeightBold:
			if italic {
				fontData = sourceCodeProBoldItalic
			} else {
				fontData = sourceCodeProBold
			}
		case WeightExtraBold:
			if italic {
				fontData = sourceCodeProExtraBoldItalic
			} else {
				fontData = sourceCodeProExtraBold
			}
		case WeightBlack:
			if italic {
				fontData = sourceCodeProBlackItalic
			} else {
				fontData = sourceCodeProBlack
			}
		default:
			return nil, fmt.Errorf("unsupported weight %s for Source Code Pro", weight)
		}

	default:
		return nil, fmt.Errorf("unsupported font family: %s", family)
	}

	if len(fontData) == 0 {
		return nil, fmt.Errorf("font data not found for %s %s italic=%v", family, weight, italic)
	}

	font, err := truetype.Parse(fontData)
	if err != nil {
		return nil, fmt.Errorf("parsing font: %w", err)
	}
	return font, nil
}

// LoadIBMPlexMono loads the default IBM Plex Mono font (ExtraLight)
func LoadIBMPlexMono() (*truetype.Font, error) {
	return LoadFont(FamilyIBMPlexMono, WeightExtraLight, false)
}

// LoadIBMPlexMonoRegular loads IBM Plex Mono Regular font
func LoadIBMPlexMonoRegular() (*truetype.Font, error) {
	return LoadFont(FamilyIBMPlexMono, WeightRegular, false)
}

// LoadIBMPlexMonoBold loads IBM Plex Mono Bold font
func LoadIBMPlexMonoBold() (*truetype.Font, error) {
	return LoadFont(FamilyIBMPlexMono, WeightBold, false)
}
