package tins2020

import (
	"fmt"

	"github.com/veandco/go-sdl2/sdl"
	"github.com/veandco/go-sdl2/ttf"
	"opslag.de/schobers/fs/vfs"
)

type TextAlignment int

const (
	TextAlignmentLeft TextAlignment = iota
	TextAlignmentCenter
	TextAlignmentRight
)

type Font struct {
	*ttf.Font
}

func (f *Font) Render(renderer *sdl.Renderer, text string, color sdl.Color) (*Texture, error) {
	surface, err := f.RenderUTF8Blended(text, color)
	if err != nil {
		return nil, err
	}
	defer surface.Free()
	texture, err := NewTextureFromSurface(renderer, surface)
	if err != nil {
		return nil, err
	}
	return texture, nil
}

func (f *Font) RenderCopyAlign(renderer *sdl.Renderer, text string, pos Point, color sdl.Color, align TextAlignment) error {
	texture, err := f.Render(renderer, text, color)
	if err != nil {
		return err
	}
	defer texture.Destroy()
	size := texture.Size()
	switch align {
	case TextAlignmentLeft:
		texture.Copy(renderer, Pt(pos.X, pos.Y-size.Y))
	case TextAlignmentCenter:
		texture.Copy(renderer, Pt(pos.X-(size.X/2), pos.Y-size.Y))
	case TextAlignmentRight:
		texture.Copy(renderer, Pt(pos.X-size.X, pos.Y-size.Y))
	}
	return nil
}

func (f *Font) RenderCopy(renderer *sdl.Renderer, text string, pos Point, color sdl.Color) error {
	return f.RenderCopyAlign(renderer, text, pos, color, TextAlignmentLeft)
}

type Fonts struct {
	dir   vfs.CopyDir
	fonts map[string]*Font
}

func (f *Fonts) Init(dir vfs.CopyDir) {
	f.dir = dir
	f.fonts = map[string]*Font{}
}

func (f *Fonts) Font(name string) *Font { return f.fonts[name] }

type FontDescriptor struct {
	Name string
	Path string
	Size int
}

func (f *Fonts) LoadDesc(fonts ...FontDescriptor) error {
	for _, desc := range fonts {
		err := f.Load(desc.Name, desc.Path, desc.Size)
		if err != nil {
			return fmt.Errorf("error loading '%s'; error: %v", desc.Name, err)
		}
	}
	return nil
}

func (f *Fonts) Load(name, path string, size int) error {
	fontPath, err := f.dir.Retrieve(path)
	if err != nil {
		return err
	}
	font, err := ttf.OpenFont(fontPath, size)
	if err != nil {
		return err
	}
	if font, ok := f.fonts[name]; ok {
		font.Close()
	}
	f.fonts[name] = &Font{font}
	return nil
}

func (f *Fonts) Destroy() {
	if f.fonts == nil {
		return
	}
	for _, f := range f.fonts {
		f.Close()
	}
}