package main

import (
	"encoding/json"
	"fmt"

	static "github.com/gin-contrib/static"
	"github.com/gin-gonic/gin"
	"gopkg.in/olahol/melody.v1"
)

type Msg struct {
	mtype   string `json:"mtype"`
	payload []byte `json:"payload"`
}

type Handler struct {
	MType    string
	Callback func(ConInfo, *Msg)
}

type ConInfo struct {
	melody  *melody.Melody
	session *melody.Session
}

type WSServer struct {
	handler map[string]*Handler
	gin     *gin.Engine
	melody  *melody.Melody
}

func NewWSServer(gin *gin.Engine, melody *melody.Melody) *WSServer {
	newWSServer := WSServer{handler: map[string]*Handler{}, gin: gin, melody: melody}
	for _, i := range newWSServer.get_default_handler() {
		newWSServer.register_handler(i)
	}
	return &newWSServer
}

func (wss *WSServer) start() {
	wss.gin.Use(static.Serve("/", static.LocalFile("./public", true)))

	wss.gin.GET("/ws", func(c *gin.Context) {
		fmt.Println("handling websocket")
		wss.melody.HandleRequest(c.Writer, c.Request)
	})

	wss.melody.HandleMessage(func(s *melody.Session, rawMsg []byte) {
		fmt.Println("new websocket message")
		msg := Msg{}
		err := json.Unmarshal(rawMsg, &msg)
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println("new message: ", msg.mtype)
		coninfo := ConInfo{melody: wss.melody, session: s}
		wss.handler[msg.mtype].Callback(coninfo, &msg)
		//m.BroadcastOthers(msg, s)
	})

	fmt.Println("starting on :5000")
	wss.gin.Run(":5000")
}

func (wss *WSServer) register_handler(newHandler *Handler) {
	wss.handler[newHandler.MType] = newHandler
}

func (wss *WSServer) get_default_handler() []*Handler {
	defaultHander := []*Handler{}
	handleJ := &Handler{MType: "J", Callback: func(coninfo ConInfo, msg *Msg) {
		remsg := *msg
		remsg.payload = []byte("default")
		jsonMsg, _ := json.Marshal(remsg)
		coninfo.session.Write(jsonMsg)
	}}
	defaultHander = append(defaultHander, handleJ)
	return defaultHander
}

func main() {
	gin := gin.Default()
	melody := melody.New()
	wss := NewWSServer(gin, melody)
	wss.start()
}
