package main

import (
	"fmt"
	"log"
	"tgk-touch/internal/module/maincontrollerClient"
	"time"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/towgo/towgo/errors/tcode"
	"github.com/towgo/towgo/lib/system"
	"github.com/towgo/towgo/lib/www"
	"github.com/towgo/towgo/towgo"
	"go.uber.org/zap"

	"tgk-touch/internal/core"
	g "tgk-touch/internal/global"
	"tgk-touch/internal/initialize"
)

func main() {
	log.SetFlags(log.Lshortfile | log.LstdFlags)
	defer func() {
		if exception := recover(); exception != nil {
			if v, ok := exception.(error); ok && gerror.HasStack(v) {
				zap.S().Errorf("err %+v \n", v)
			} else {
				zap.S().Errorf("recover exception %+v\n", gerror.NewCodef(tcode.CodeInternalPanic, "%+v", exception))
			}
		}
	}()
	appInit()
	start()
}

func appInit() {
	initialize.Init()
	kioskInfof("app initialized")
}

func start() {
	kioskInfof("service start begin")
	serialPortAddress := g.Config().Tty.SerialPortAddress
	if serialPortAddress == "" {
		kioskErrorf("tty serialPortAddress is empty")
		panic(gerror.New("tty.serialPortAddress is empty"))
	}

	baudRate := g.Config().Tty.BaudRate
	if baudRate == 0 {
		zap.S().Info("tty.baudRate 未配置，使用默认 9600")
		baudRate = 9600
	}
	kioskInfof("tty config loaded serial=%s baud=%d", serialPortAddress, baudRate)

	towgo.SetFunc("/getMessageInterval", func(rpcConn towgo.JsonRpcConnection) {
		rpcConn.WriteResult(g.Config().MessageInterval)
	})
	if err := maincontrollerClient.UseSerialPort(serialPortAddress, baudRate); err != nil {
		kioskErrorf("serial port start failed serial=%s baud=%d err=%v", serialPortAddress, baudRate, err)
		panic(gerror.Wrap(err, "串口启动失败"))
	}
	kioskInfof("serial port started serial=%s baud=%d", serialPortAddress, baudRate)

	webServer := www.WebServer{}
	webServer.Wwwroot = system.GetPathOfProgram() + "wwwroot"
	webServer.Index = []string{"index.html"}
	kioskInfof("web server configured wwwroot=%s index=%v", webServer.Wwwroot, webServer.Index)

	g.HttpServerMux().HandleFunc("/", webServer.WebServerHandller)
	g.HttpServerMux().HandleFunc("/jsonrpc/websocket", towgo.DefaultWebSocketServer.WebsocketServiceHandller.ServeHTTP)
	g.HttpServerMux().HandleFunc("/jsonrpc", towgo.HttpHandller)
	towgo.DefaultExec = func(rpcConn towgo.JsonRpcConnection) {
		if exception := recover(); exception != nil {
			msg := "unknown panic"
			if v, ok := exception.(error); ok && gerror.HasStack(v) {
				g.Log().Error("towgo jsonrpc exception \n", v)
				msg = v.Error()
			} else {
				g.Log().Error("towgo jsonrpc recover exception  \n", gerror.NewCodef(tcode.CodeInternalPanic, "%+v", exception))
				msg = fmt.Sprintf("%+v", exception)
			}

			rpcConn.WriteError(500, rpcConn.GetRpcRequest().Method+":"+msg)
		}
	}

	if err := runStartupChecks(); err != nil {
		kioskErrorf("skip firefox client startup because startup checks failed err=%v", err)
	} else {
		kioskInfof("starting firefox client goroutine port=%d", g.Config().Server.Port)
		go func(port int) {
			time.Sleep(500 * time.Millisecond)
			runClient(port)
		}(g.Config().Server.Port)
	}
	core.RunServer()
}

func runStartupChecks() error {
	startedAt := time.Now()
	kioskInfof("startup checks begin")
	if err := install(); err != nil {
		kioskErrorf("startup checks failed elapsed=%s err=%v", time.Since(startedAt).Round(time.Millisecond), err)
		return err
	}
	kioskInfof("startup checks done elapsed=%s", time.Since(startedAt).Round(time.Millisecond))
	return nil
}

// TODO Build Cmd  CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o m9zCtrlTty-arm64 .
