package display

import (
	"errors"
	"fmt"
	"image/color"

	"git.dvdt.dev/david/bitcoin-ticker-pi/fonts"
	rgbmatrix "git.dvdt.dev/david/bitcoin-ticker-pi/go-rpi-rgb-led-matrix"
)

var (
	ErrUnsupportedSlotHeight = errors.New("unsupported slot height")
)

type Segment struct {
	Text   string
	Color  color.RGBA
	bitmap [][]color.RGBA
}

func (s *Segment) Draw(canvas *rgbmatrix.Canvas, x, y int) {
	for i, row := range s.bitmap {
		drawRow(canvas, row, x, y+i)
	}
}

func drawRow(canvas *rgbmatrix.Canvas, row []color.RGBA, x, y int) {
	for i := 0; i < len(row); i++ {
		canvas.Set(x+i, y, row[i])
	}
}

type Slot struct {
	segmentLimit  int
	segmentHeight int
	segmentWidth  int
	x, y          int
	text          []Segment
}

func NewSlot(limit, height, width, x, y int) *Slot {
	return &Slot{
		segmentLimit:  limit,
		segmentHeight: height,
		segmentWidth:  width,
		x:             x,
		y:             y,
		text:          []Segment{},
	}
}

func (s *Slot) Update(text []Segment) error {
	if len(text) > s.segmentLimit {
		text = text[:s.segmentLimit-3]
		text = append(text, []Segment{
			{Text: ".", Color: fonts.White},
			{Text: ".", Color: fonts.White},
			{Text: ".", Color: fonts.White},
		}...)
	}

	var font fonts.Font
	switch s.segmentHeight {
	case 5:
		font = fonts.Face5x4
	case 7:
		font = fonts.Face7x5
	case 9:
		font = fonts.Face9x6
	case 13:
		font = fonts.Face13x8
	default:
		return fmt.Errorf("%w: %d", ErrUnsupportedSlotHeight, s.segmentHeight)
	}

	for i, t := range text {
		c, err := font.ToColor(t.Text, t.Color)
		if err != nil {
			return err
		}
		text[i].bitmap = c
	}
	s.text = text
	return nil
}

func (s *Slot) Draw(canvas *rgbmatrix.Canvas) {
	for i, segment := range s.text {
		segment.Draw(canvas, s.x+(i*s.segmentWidth), s.y)
	}
}
