package web

import (
	"fmt"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"

	"th7/data/core"
	"th7/ports"
)

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

func (g *GinAdapter) getRatio() core.Ratio {
	return g.corePort.GetRatio()
}

func (g *GinAdapter) RatioHandler(c *gin.Context) {
	ratio := g.getRatio()
	c.JSON(http.StatusOK, ratio)
}

func (g *GinAdapter) getChannels() []core.Channel {
	return g.corePort.GetChannels()
}

func (g *GinAdapter) ChannelsHandler(c *gin.Context) {
	channels := g.getChannels()
	c.JSON(http.StatusOK, channels)
}

func (g *GinAdapter) getChannelByID(id int) (core.Channel, error) {
	return g.corePort.GetChannel(id)
}

func (g *GinAdapter) ChannelByIDHandler(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": err,
		})
		return
	}

	channel, err := g.getChannelByID(id)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": err,
		})
		return
	}

	c.JSON(http.StatusOK, channel)
}

func (g *GinAdapter) getTimestamp() string {
	return time.Now().Format(time.RFC1123)
}

func (g *GinAdapter) TimestampHandler(c *gin.Context) {
	ts := g.getTimestamp()
	c.JSON(http.StatusOK, gin.H{
		"time": ts,
	})
}

func (g *GinAdapter) DataHandler(c *gin.Context) {
	timestamp := g.getTimestamp()
	ratio := g.getRatio()
	channels := g.getChannels()

	c.JSON(http.StatusOK, gin.H{
		"time":     timestamp,
		"ratio":    ratio,
		"channels": channels,
	})
}

func (g *GinAdapter) IndexHandler(c *gin.Context) {
	c.HTML(http.StatusOK, "page_index", gin.H{
		"title": "TH7",
	})
}

func NewGinAdapter(corePort ports.CorePort, port int) *GinAdapter {
	var adapter GinAdapter

	adapter.corePort = corePort
	adapter.port = port

	adapter.router = gin.Default()

	adapter.router.GET("/ratio", adapter.RatioHandler)
	adapter.router.GET("/channels", adapter.ChannelsHandler)
	adapter.router.GET("/channel/:id", adapter.ChannelByIDHandler)
	adapter.router.GET("/time", adapter.TimestampHandler)
	adapter.router.GET("/data", adapter.DataHandler)

	adapter.router.LoadHTMLGlob("./templates/*.tmpl")
	adapter.router.Static("/assets", "./static")
	adapter.router.GET("/", adapter.IndexHandler)

	return &adapter
}

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