package web

import (
	"context"
	"time"

	"github.com/gofiber/websocket/v2"
	"go.mongodb.org/mongo-driver/bson"
	"krakatoa.net/backend/modules/cache"
	"krakatoa.net/backend/modules/kraProtocol"
	"krakatoa.net/backend/modules/logger"
	"krakatoa.net/backend/modules/mongo"
	"krakatoa.net/backend/modules/structs"
	serverCommunication "krakatoa.net/backend/serverCommunication"
)

//var clients = make(map[string]*structs.Client)
var register = make(chan *websocket.Conn)
var broadcast = make(chan structs.SocketBroadcastData)
var unregister = make(chan *websocket.Conn)

func RunHub() {
	for {
		select {
		case connection := <-register:
			token := connection.Cookies("token")

			clientDb := structs.WebClientDb{}

			err := mongo.PlayersCollection.FindOne(context.TODO(), bson.D{{"$or", bson.A{bson.D{{"voiceSessionToken", token}}, bson.D{{"mobileSessionToken", token}}}}}).Decode(&clientDb)

			if err != nil {
				logger.Mongo.Println("err", err)
			}
			logger.Web.Debugln("getClientByUuid", clientDb, token)

			client := serverCommunication.GetWebClientByUuid(clientDb.Uuid)

			if token == clientDb.VoiceSessionToken { // voice
				client.VoiceConn = connection
				logger.Web.Println("voice")
			} else if token == clientDb.MobileSessionToken { // mobile
				client.MobileConn = connection
				logger.Web.Println("mobile")
			} else { // token invald
				logger.Web.Println("invalid")
			}

			logger.Web.Debugln("finish client", client)

		case data := <-broadcast:
			logger.Web.Println("message received", data.Msg)

			status, cmdID, dest, cmdNumber, args := kraProtocol.DecodeMessage(data.Msg)

			// check if it is a connection from voice or mobile
			for _, client := range cache.WebClients {
				if client.MobileConn == data.Conn || client.VoiceConn == data.Conn {
					go serverCommunication.HandleWebMessage(client.VoiceConn == data.Conn, data.Conn, client.Uuid, status, cmdID, dest, cmdNumber, args)
					break
				}
			}

		case connection := <-unregister:
			for uuid, client := range cache.WebClients {
				logger.Web.Println("client unregister", client)
				if client.MobileConn == connection {
					client.MobileConn = nil
					client.MobileCmdIDs = []int{}
					logger.Web.Println("delete mobileConn", client)

					serverCommunication.SendMessageToServer(kraProtocol.DestProxy, uuid, "1")
				} else if client.VoiceConn == connection {
					client.VoiceConn = nil
					client.VoiceCmdIDs = []int{}
					logger.Web.Println("delete voiceConn", client)

					serverCommunication.SendMessageToServer(kraProtocol.DestProxy, uuid, "2")
				}

				logger.Web.Println("client after updating", client)

				if client.VoiceConn == nil && client.MobileConn == nil {
					delete(cache.WebClients, uuid)
					logger.Web.Println("delete client", client)
				}
			}
		}
	}
}

func Test() {
	for {
		for _, client := range cache.WebClients {

			raw := kraProtocol.SendMessageToClient(1, 1, 2, "this a test ping")

			if client.VoiceConn != nil {
				client.SendBinaryMessage(client.VoiceConn, raw)
			}

			if client.MobileConn != nil {
				client.SendBinaryMessage(client.MobileConn, raw)
			}
		}
		time.Sleep(30 * time.Second)
	}
}
