package serverCommunication

import (
	"github.com/gofiber/websocket/v2"
	"krakatoa.net/backend/modules/cache"
	"krakatoa.net/backend/modules/kraProtocol"
	"krakatoa.net/backend/modules/logger"
	"krakatoa.net/backend/modules/structs"
)

func GetMinecraftClientByName(Name string) *structs.MinecraftClient {
	for name, client := range cache.MinecraftClients {
		if name == Name {
			logger.Minecraft.Debugln("return mc client", client.Name)
			return client
		}
	}

	logger.Minecraft.Warnln("mc client nil")

	return nil
}

func getMinecraftServerNameByDest(dest int) string {
	if dest == kraProtocol.DestProxy {
		return "proxy-1"
	} else { // get players current server from db if dest is 11
		return "lobby-1"
	}
}

func HandleMinecraftMessage(conn *websocket.Conn, status int, cmdID int, dest int, playerUuid string, cmdNumber int, args string) {
	var raw []byte
	var err error

	if dest == kraProtocol.DestBackend {
		resArgs := minecraftCommandHandler(cmdNumber, playerUuid)

		if status == kraProtocol.StatusGet {
			raw = kraProtocol.SendMessageToJava(kraProtocol.StatusReply, cmdID, 0, playerUuid, cmdNumber, resArgs)

			err = conn.WriteMessage(websocket.BinaryMessage, raw)

			if err != nil {
				logger.Minecraft.Warnln("write:", err)
			}
		}
	} else if dest == kraProtocol.DestVoice || dest == kraProtocol.DestMobile { // forwarding messsage to voice or mobile
		destConn := getConnForDest(dest, playerUuid)

		if destConn != nil {
			raw = kraProtocol.SendMessageToClient(status, cmdID, cmdNumber, args)

			err = destConn.WriteMessage(websocket.BinaryMessage, raw)

			if err != nil {
				logger.Minecraft.Warnln("write:", err)
			}
		} else { // conn is not connected
			raw = kraProtocol.SendMessageToJava(kraProtocol.StatusErrTryAgain, cmdID, dest, playerUuid, cmdNumber, args)

			err = conn.WriteMessage(websocket.BinaryMessage, raw)

			if err != nil {
				logger.Minecraft.Warnln("write:", err)
			}
		}
	} else if dest == kraProtocol.DestProxy {
		client := GetMinecraftClientByName("proxy-1")

		raw := kraProtocol.SendMessageToJava(status, cmdID, dest, playerUuid, cmdNumber, args)

		err = client.Connection.WriteMessage(websocket.BinaryMessage, raw)

		if err != nil {
			logger.Minecraft.Warnln("write:", err)
		}
	}
}

func minecraftCommandHandler(cmdNumber int, playerUuid string) (args string) {
	switch cmdNumber {
	case 10: // testing
		return IsVoiceAndMobileSocketConnected(playerUuid)
	default:
		return "default"
	}
}

// Deprecated: only for testing, use SendMessageToMinecraftServer instead
func SendMessageToServer(dest int, playerUuid string, args string) {
	mcClient := GetMinecraftClientByName(getMinecraftServerNameByDest(dest))

	raw := kraProtocol.SendMessageToJava(10, 1, 2, playerUuid, 15, args)

	mcClient.Connection.WriteMessage(websocket.BinaryMessage, raw)
}

func SendMessageToMinecraftServer(status int, dest int, playerUuid string, cmdNumber int, args string) {
	cmdID := 0
	raw := kraProtocol.SendMessageToJava(status, cmdID, dest, playerUuid, cmdNumber, args)

	serverName := getMinecraftServerNameByDest(dest)

	mcClient := GetMinecraftClientByName(serverName)

	err := mcClient.Connection.WriteMessage(websocket.BinaryMessage, raw)

	if err != nil {
		logger.Minecraft.Warnln("err", err)
	}
}
