package gui

import (
	"bytes"
	"io"
	"os"

	"golang.org/x/image/font"
	"golang.org/x/image/font/opentype"
	"golang.org/x/image/font/sfnt"
)

type Font struct {
	font  *sfnt.Font
	faces map[int]font.Face
}

func LoadOpenTypeFont(otfFile string) (*Font, error) {
	ff, err := os.Open(otfFile)
	if err != nil {
		return nil, err
	}
	return LoadFontFromReaderAt(ff)
}

func LoadFontFromBytes(data []byte) (*Font, error) {
	return LoadFontFromReaderAt(bytes.NewReader(data))
}

func LoadFontFromReaderAt(r io.ReaderAt) (*Font, error) {
	fnt, err := opentype.ParseReaderAt(r)
	if err != nil {
		return nil, err
	}

	return &Font{
		font:  fnt,
		faces: map[int]font.Face{},
	}, nil
}

func (f *Font) FaceErr(fontSize int) (face font.Face, err error) {
	if v, ok := f.faces[fontSize]; ok {
		return v, nil
	}

	face, err = opentype.NewFace(f.font, &opentype.FaceOptions{
		Size:    float64(fontSize),
		DPI:     72,
		Hinting: font.HintingFull,
	})

	if err == nil {
		f.faces[fontSize] = face
	}

	return face, err
}

func (f *Font) Face(fontSize int) font.Face {
	face, err := f.FaceErr(fontSize)
	if err != nil {
		panic(err)
	}
	return face
}

func (f *Font) Close() error {
	for _, face := range f.faces {
		if err := face.Close(); err != nil {
			return err
		}
	}
	return nil
}
