package main

import (
	"context"
	"fmt"
	"image/color"
	"log"
	"time"

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

const (
	RefreshRateHz = 60
	MempoolURL    = "wss://mempool.dvdt.dev/v1/api/ws"
)

func main() {
	cfg := rgbmatrix.DefaultConfig
	cfg.Rows = 32
	cfg.Cols = 64

	m, _ := rgbmatrix.NewRGBLedMatrix(&cfg)
	c := rgbmatrix.NewCanvas(m)

	d := display.New(c,
		display.NewSlot(9, 5, 4, 0, 0),
		display.NewSlot(5, 5, 4, 44, 0),
		display.NewSlot(7, 13, 8, 5, 9),
		display.NewSlot(12, 5, 4, 7, 27),
		display.NewSlot(8, 5, 4, 28, 27),
	)

	ctx, cancel := context.WithCancel(context.Background())
	ticker := time.NewTicker(time.Second / RefreshRateHz)
	tdone := make(chan struct{})
	mdone := make(chan struct{})
	blocks := make(chan mempool.Block)
	errs := make(chan error)

	mp := mempool.New(MempoolURL)
	err := mp.Init()
	if err != nil {
		log.Fatal(err)
	}

	go func(done chan struct{}, t *time.Ticker) {
		for {
			select {
			case <-done:
				return
			case <-ticker.C:
				updateSlots(d, 44000, 821000, 100, 200, 300)
			}
		}
	}(tdone, ticker)
}

func updateSlots(d *display.Display, price, height, lfee, mfee, hfee int) error {
	priceStr := fmt.Sprintf("%d", price)
	var priceSegments []display.Segment
	priceSegments = append(priceSegments, strToDisplaySegments("dollar", fonts.Green)...)
	priceSegments = append(priceSegments, strToDisplaySegments(fmt.Sprintf("%d", price), fonts.White)...)

	err := d.UpdateTopLeft(priceSegments)
	if err != nil {
		return err
	}

	var moscowTimeSegments []display.Segment
	moscowTimeSegments = append(moscowTimeSegments, strToDisplaySegments("satoshi", fonts.Orange)...)
	moscowTimeSegments = append(moscowTimeSegments, strToDisplaySegments(fmt.Sprintf("%d", 100000000/price), fonts.White)...)

	err = d.UpdateTopRight(moscowTimeSegments)
	if err != nil {
		return err
	}

	var heightSegments []display.Segment
	heightSegments = append(heightSegments, strToDisplaySegments("height", fonts.Blue)...)
	heightSegments = append(heightSegments, strToDisplaySegments(fmt.Sprintf("%d", height), fonts.White)...)

	err = d.UpdateCenter(heightSegments)
	if err != nil {
		return err
	}

	return nil
}

func strToDisplaySegments(s string, c color.Color) []display.Segment {
	var segs []display.Segment
	for _, r := range s {
		segs = append(segs, display.Segment{Text: string(r), Color: c})
	}
	return segs
}
