class BotManagerHostEnhanced
{
	list = new Map();
	messageInterface = "ingame";

	constructor()
	{

	}

	addBot(name, object)
	{
		if (!("toggle" in object))
			object.toggle = function () { this.active = !this.active; }

		if (!("react" in object))
			object.react = function () { }

		if (!("load" in object))
			object.load = function () { }

		autociv_patchApplyN(object, "load", function (target, that, args)
		{
			let [active] = args
			that.loaded = true
			that.active = active
			return target.apply(that, args)
		})

		this.list.set(name, object)
	}

	get(name)
	{
		return this.list.get(name)
	}

	sendMessage(text)
	{
		log("debug botmanager_HostEnhanced.js:sendMessage:text:"+text);
		warn("Can't send sendMessage2 - HostEnhanced");
	}

	selfMessage(text)
	{
		log("debug botmanager_HostEnhanced.js:selfMessage:text:"+text);
		//warn("Can't send selfMessage2 - HostEnhanced"+text);
		warn(text);
	}

	/**
	 *
	 * @returns {Boolean} - True means to stop message flow
	 */
	react(msg)
	{
		let data = this.pipe(msg)
		if (!data)
			return false

		for (let [name, bot] of this.list)
			if (bot.loaded && bot.active && bot.react(data))
				return true
		return false
	}

	pipe(msg)
	{
		if (!msg)
			return
		return this.pipeWith[this.messageInterface].pipe(msg)
	}

	pipeWith = {
		"lobby": {
			"pipe": function (msg)
			{
				return this.types[msg.type]?.(msg)
			},
			"types":
			{
				"chat": msg =>
				{
					switch (msg.level)
					{
						case "room-message": return {
							"type": "chat",
							"receiver": Engine.LobbyGetNick(),
							"sender": msg.from,
							"message": msg.text
						}
						case "join": return {
							"type": "join",
							"receiver": Engine.LobbyGetNick(),
							"sender": msg.nick,
							"message": ""
						}

					}
				}
			}
		},
		"gamesetup": {
			"pipe": function (msg)
			{
				return this.types[msg.type]?.(msg)
			},
			"types":
			{
				"chat": function (msg)
				{
					// Ignore message if it comes from the AI (will have translate=true)
					if (msg.translate)
						return
					if (Engine.GetPlayerGUID() === undefined ||
						g_PlayerAssignments[Engine.GetPlayerGUID()] === undefined ||
						msg.guid === undefined ||
						g_PlayerAssignments[msg.guid] === undefined)
						return

					return {
						"type": "chat",
						"receiver": splitRatingFromNick(g_PlayerAssignments[Engine.GetPlayerGUID()].name).nick,
						"sender": splitRatingFromNick(g_PlayerAssignments[msg.guid].name).nick,
						"message": msg.text
					}
				}
				// TODO JOIN, LEAVE (AKA newAssignments)
			}
		},
		"ingame": {
			"pipe": function (msg)
			{
				return this.types[msg.type]?.(msg)
			},
			"types":
			{
				"message": function (msg)
				{
					// Ignore message if it comes from the AI (will have translate=true)
					if (msg.translate)
						return
					if (Engine.GetPlayerGUID() === undefined ||
						g_PlayerAssignments[Engine.GetPlayerGUID()] === undefined ||
						msg.guid === undefined ||
						g_PlayerAssignments[msg.guid] === undefined)
						return

					return {
						"type": "chat",
						"receiver": splitRatingFromNick(g_PlayerAssignments[Engine.GetPlayerGUID()].name).nick,
						"sender": splitRatingFromNick(g_PlayerAssignments[msg.guid].name).nick,
						"message": msg.text,
					}
				},
				"rejoined": function (msg)
				{
					if (Engine.GetPlayerGUID() === undefined ||
						g_PlayerAssignments[Engine.GetPlayerGUID()] === undefined ||
						msg.guid === undefined ||
						g_PlayerAssignments[msg.guid] === undefined)
						return

					return {
						"type": "join",
						"receiver": splitRatingFromNick(g_PlayerAssignments[Engine.GetPlayerGUID()].name).nick,
						"sender": splitRatingFromNick(g_PlayerAssignments[msg.guid].name).nick,
						"guid": msg.guid
					}
				}
			}
		}
	}

	setMessageInterface(messageInterface)
	{
		this.messageInterface = messageInterface
/*
		if ("lobby" == this.messageInterface)
		{
			log("debug botmanager_HostEnhanced.js:setMessageInterface_lobby");
			this.sendMessage = text =>
			{
				if (Engine.HasXmppClient())
					Engine.LobbySendMessage(text)
			}

			this.selfMessage = text =>
			{
				let ftext = setStringTags(`== ${text}`, { "font": "sans-bold-13" })
				g_LobbyHandler.lobbyPage.lobbyPage.panels.chatPanel.chatMessagesPanel.
					addText(Date.now() / 1000, ftext)
			}
		}
	*/
	/*	else if ("gamesetup" == this.messageInterface) */
		if ("gamesetup" == this.messageInterface) 
		{
			log("debug botmanager_HostEnhanced.js:setMessageInterface_gamesetup");
			this.sendMessage = text =>
			{
				if (Engine.HasNetClient())
					Engine.SendNetworkChat(text)
			}

			this.selfMessage = text =>
			{
				let ftext = setStringTags(`== ${text}`, { "font": "sans-bold-13" })
				g_SetupWindow.pages.GameSetupPage.panels.chatPanel.chatMessagesPanel.
					addText(ftext)
			}
		}
		else if ("ingame" == this.messageInterface)
		{
			log("debug botmanager_HostEnhanced.js:setMessageInterface_ingame");

			this.sendMessage = text =>
			{
				log("debug botmanager_HostEnhanced.js:setMessageInterface_ingame:text"+text);
				
				if (Engine.HasNetClient())
				{					
					for (let line of text.split("\n"))
						log("debug botmanager_HostEnhanced.js:setMessageInterface_ingame:line"+line);
						Engine.SendNetworkChat(line)
				}
				else
				

					// Only used for offline games.
					g_Chat.ChatMessageHandler.handleMessage({
						"type": "message",
						"guid": "local",
						"text": text
					})
			}

			g_Chat.ChatMessageHandler.registerMessageFormat("hostenhanced_self", new ChatMessageFormatHostEnhancedSelf())

			this.selfMessage = text => g_Chat.ChatMessageHandler.handleMessage({
				"type": "message",
				"text": text
			})
			log("debug:botmanager_HostEnhanced.js:setMessageInterface_ingame:this.selfMessage"+text);

		}
		else		
			warn(`Invalid message interface ${this.messageInterface}`)
	}
}

var botManagerHostEnhanced = new BotManagerHostEnhanced();

function selfMessage(text) { botManagerHostEnhanced.selfMessage(text) }

function sendMessage(text)
{
	// Messages reduced to the first 255 letters so, send it split if exceeded
	const numChunks = Math.ceil(text.length / sendMessage.maxChunkLength);
	for (let i = 0; i < numChunks; ++i)
		botManagerHostEnhanced.sendMessage(text.substr(i * sendMessage.maxChunkLength, sendMessage.maxChunkLength));
}

sendMessage.maxChunkLength = 256 - 1;

// ********* Bot botManagerHostEnhanced.addBot order matters ***********

botManagerHostEnhanced.addBot("ban", {
	"name": "Ban bot",
	"react": function (data)
	{
		if (data.type != "chat")
			return;

		return this.instance.hasValue(data.sender);
	},
	"load": function (active)
	{
		this.instance = new ConfigJSON(`ban`);
	}
});

