package main

import (
	"context"
	"fmt"
	"log"
	"math"
	"os"
	"os/signal"
	"syscall"
	"time"

	"gitea.unprism.ru/yotia/display-test/display"
	"gitea.unprism.ru/yotia/display-test/drawer"

	"gitea.unprism.ru/KRBL/sim-modem/api/modem"
)

const (
	displayUpdateTimeout = 10 * time.Millisecond
)

func main() {
	log.Println("CGSG forever!!!")

	ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer cancel()
	// Just for logs
	go func(ctx context.Context) {
		<-ctx.Done()
		log.Println("GOT INTERUPT SIGNAL")
	}(ctx)

	if err := mainE(ctx); err != nil {
		log.Println("MAIN finished with error:", err.Error())
	}
	log.Println("END")
}

var logger *log.Logger
var dev display.Display
var d drawer.Drawer

var m modem.Modem

func DrawProgress(ctx context.Context, timeout time.Duration) error {
	deadline := time.Now().Add(timeout)

	// Draw outline
	x := 0
	y := drawer.FontCharH + 4
	w := dev.GetImg().Rect.Dx()
	h := drawer.FontCharH - 4

	d.PutBar(x, y, x+w, y+h, 255)
	gap := 3

	// Draw body
	x += gap
	y += gap
	w -= 2 * gap
	h -= 2 * gap
	lastX := x

	for {
		select {
		case <-ctx.Done():
			return nil
		case <-time.After(displayUpdateTimeout):
			value := 1 - float64(time.Until(deadline).Milliseconds())/float64(timeout.Milliseconds())
			newX := x + int(value*float64(w))
			// Draw
			d.FillBar(lastX, y, newX, y+h, 255)
			lastX = newX
			if value >= 1 {
				return nil
			}
			d.Flush()
		}
	}
}

func Init(ctx context.Context) error {
	// Display init
	var err error
	dev, err = display.New(log.New(log.Writer(), "display", log.LstdFlags), display.MT12232A)
	if err != nil {
		return fmt.Errorf("new display: %w", err)
	}
	logger.Println("Display inited")

	// Create drawer
	d := drawer.New(dev)

	d.Clear()
	//d.FillBar(0, 0, 10, 10, 1)
	stTime := time.Now()
	for {
		select {
		case <-ctx.Done():
			return nil
		default:
			t := float64(time.Since(stTime).Milliseconds()) / 1000
			x := math.Sin(t)*10 + 5
			y := math.Cos(t)*10 + 5
			d.Clear()
			d.PutText(int(x), int(y), "CGSG forever")
			stT := time.Now()
			d.Flush()
			logger.Println("Iteration time:", time.Since(stT))
		}
	}
	//d.PutText(0, 0, "можно 4 строки впихнуть")
	//d.PutText(0, drawer.FontCharH+drawer.LineGap, "каждая буква 5x7")
	//d.PutText(0, (drawer.FontCharH+drawer.LineGap)*2, "+ русский через жопу")
	//d.PutText(0, (drawer.FontCharH+drawer.LineGap)*3, "KRBL forever!!")

	// Modem init
	//mInitCtx, mInitCtxCancel := context.WithCancel(ctx)
	//go DrawProgress(mInitCtx, 13*time.Second)
	//defer mInitCtxCancel()
	//
	//m = modem.New(log.New(logger.Writer(), "modem : ", log.LstdFlags))
	//if err := m.Init(); err != nil {
	//	return fmt.Errorf("modem init: %w", err)
	//}
	//logger.Println("Display inited")
	//mInitCtxCancel()
	//
	//d.Clear()
	//d.PutText(0, d.GetFont().Metrics().Height.Ceil(), "Modem inited.")
	//d.PutText(0, d.GetFont().Metrics().Height.Ceil()*2, "Starting test...")
	//d.Flush()
	return nil
}
func Close() {
	//m.Close()
	//if d != nil {
	//	d.Clear()
	//	d.Flush()
	//}
	dev.Close()
}

//func MainLoop(ctx context.Context) error {
//	mainLoopTimeout := time.Second
//
//	frameCounter := 0
//	deadline := time.Now().Add(100 * time.Millisecond)
//	for {
//		select {
//		case <-ctx.Done():
//			return nil
//		case <-time.After(time.Until(deadline)):
//			deadline = time.Now().Add(mainLoopTimeout)
//
//			st, _ := m.Gps().GetStatus()
//			data := m.GetData()
//
//			coordsStr := fmt.Sprintf("%03d°%02.0f'%s %03d°%02.0f'%s",
//				int(data.Latitude), (data.Latitude-float64(int(data.Latitude)))*100, data.LatitudeIndicator,
//				int(data.Longitude), (data.Longitude-float64(int(data.Longitude)))*100, data.LongitudeIndicator)
//			var str1 string
//			var str2 string
//
//			if frameCounter%4 < 2 {
//				str2 = fmt.Sprintf("Sat. count: %d", st.FoundSatelitesCount)
//			} else {
//				str2 = coordsStr
//			}
//			str1 = fmt.Sprintf("%s", time.Now().Format("15:04:05"))
//
//			d.Clear()
//			d.PutText(0, d.GetFont().Metrics().Height.Ceil(), str1)
//			d.PutText(0, d.GetFont().Metrics().Height.Ceil()*2, str2)
//			d.Flush()
//			frameCounter++
//		}
//	}
//}

func mainE(ctx context.Context) error {
	logger = log.New(os.Stdout, "main : ", log.LstdFlags)
	//
	if err := Init(ctx); err != nil {
		return err
	}
	//if err := dev.Test(ctx); err != nil {
	//	return err
	//}
	defer Close()
	// if err := MainLoop(ctx); err != nil {
	// 	return err
	// }
	return nil
}