package api

import (
	"fmt"
	"log"

	"github.com/gin-gonic/gin"

	"th7/data/config"
	"th7/ports"
)

type GinAdapter struct {
	router   *gin.Engine
	corePort ports.CorePort
	cfg      config.Config
	port     int
}

func (g *GinAdapter) IndexHandler(c *gin.Context) {
	c.File("./static/index.html")
}

func NewGinAdapter(corePort ports.CorePort, cfg config.Config) *GinAdapter {
	var adapter GinAdapter

	adapter.corePort = corePort
	adapter.port = cfg.API.Port
	adapter.cfg = cfg

	gin.SetMode(gin.ReleaseMode)

	adapter.router = gin.New()

	// websockets
	manager := NewManager()
	go manager.start()

	// API
	v1 := adapter.router.Group("/v1")
	v1.GET("/data/channel/:id", adapter.GetChannelByIDHandler)
	v1.GET("/data/channels", adapter.GetChannelsHandler)
	v1.GET("/data/ratio", adapter.GetRatioHandler)
	v1.GET("/data", adapter.GetDataHandler)

	v1.GET("/config/channel/:id", adapter.GetConfigChannelByIdHandler)
	v1.GET("/config/channels", adapter.GetConfigChannelsHandler)
	v1.GET("/config/device", adapter.GetConfigDeviceHandler)
	v1.GET("/config/db", adapter.GetConfigDBHandler)

	v1.POST("/config/device", adapter.SetConfigDeviceHandler)
	v1.POST("/config/channel/:id", adapter.SetConfigChannelByIdHandler)
	v1.POST("/config/db", adapter.SetConfigDBHandler)

	adapter.router.GET("/ws", func(c *gin.Context) {
		conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
		if err != nil {
			log.Println(err)
		}

		client := &Client{
			socket:  conn,
			send:    make(chan []byte),
			manager: manager,
		}

		manager.register <- client

		go client.writer()
	})

	// start web socket service that dumps new data to websocket chan
	go startService(manager, corePort)

	// TH7 demo code. html file and javascript
	adapter.router.GET("/", adapter.IndexHandler)
	adapter.router.Static("/assets", "./static")

	return &adapter
}

func (g *GinAdapter) Run() {
	portStr := fmt.Sprintf(":%d", g.port)
	g.router.Run(portStr)
}