var MATTIE = MATTIE || {};
MATTIE.menus.multiplayer = MATTIE.menus.multiplayer || {};
MATTIE.scenes.multiplayer = MATTIE.scenes.multiplayer || {};
MATTIE.windows.multiplayer = MATTIE.windows.multiplayer || {};
MATTIE.TextManager = MATTIE.TextManager || {};
MATTIE.CmdManager = MATTIE.CmdManager || {};
MATTIE.TextManager.startGame = 'Start Game';
MATTIE.TextManager.returnToMultiplayer = 'Close Server';
MATTIE.CmdManager.startGame = 'MATTIE_Start_Game';
MATTIE.CmdManager.returnToMultiplayer = 'MATTIE_ReturnToMulti';
MATTIE.TextManager.copy = 'Copy Code';
MATTIE.CmdManager.copy = 'MATTIE_Copy_Code';
MATTIE.TextManager.show = 'Show/Hide';
MATTIE.CmdManager.show = 'MATTIE_Show_Hide';

/**
 * @description The scene for hosting a multiplayer game
 * @extends Scene_Base
 * @class
 */
MATTIE.scenes.multiplayer.host = function () {
	this.initialize.apply(this, arguments);
};
MATTIE.scenes.multiplayer.host.prototype = Object.create(MATTIE.scenes.multiplayer.base.prototype); // extend Scene_Base
MATTIE.scenes.multiplayer.host.prototype.constructor = MATTIE.scenes.multiplayer.host; // use constructor

MATTIE.scenes.multiplayer.host.prototype.create = function () {
	MATTIE.scenes.multiplayer.base.prototype.create.call(this);
	this.createWindowLayer();

	// Determine correct fallback state before opening controller
	if (MATTIE.multiplayer.userOverrideFallback === true) {
		MATTIE.multiplayer.forceFallback = true;
	} else if (MATTIE.multiplayer.userOverrideFallback === false) {
		MATTIE.multiplayer.forceFallback = false;
	}
	// If null (no override), allow auto-switch logic or defaults effectively.
	// But host open() is what initiates connections.

	MATTIE.multiplayer.hostController.open();
	this.addPlayerListWindow();
	this.addOptionsBtns();
	// this.addFallbackToggle(); // Removed separate toggle
	this.addPeerDisplayWindow();

	this._loadingInterval = setInterval(() => {
		this.animateTick();
	}, 500);

	// Setup fallback detection if not already forced
	if (!MATTIE.multiplayer.forceFallback && !MATTIE.multiplayer.fallbackAutoSwitched && MATTIE.multiplayer.userOverrideFallback === null) {
		this._connectionTimeout = setTimeout(() => {
			if (!MATTIE.multiplayer.hostController.peerId) {
				console.log('Connection timed out. Auto-switching to Fallback TCP.');
				MATTIE.multiplayer.fallbackAutoSwitched = true;
				MATTIE.multiplayer.forceFallback = true;
				MATTIE.multiplayer.hostController.open(); // Re-open with new settings

				// Re-bind to the new self instance
				this.bindToHostEvents();
			}
		}, 10000); // 10 seconds
	}

	this.bindToHostEvents();
};

MATTIE.scenes.multiplayer.host.prototype.bindToHostEvents = function () {
	if (MATTIE.multiplayer.hostController.self) {
		MATTIE.multiplayer.hostController.self.on('open', () => {
			if (this._connectionTimeout) clearTimeout(this._connectionTimeout);
			this.initListController();

			if (this._loadingInterval) {
				clearInterval(this._loadingInterval);
				this._loadingInterval = null;
			}

			this.showHideCode(true);
		});
	}
};

MATTIE.scenes.multiplayer.host.prototype.addPlayerListWindow = function () {
	this._playerWindow = new MATTIE.windows.List(0, 0, 600, 300, 'Connected Players:');
	this._playerWindow.updatePlacement(0, 15);
	this.addWindow(this._playerWindow);
};

MATTIE.scenes.multiplayer.host.prototype.initListController = function () {
	MATTIE.multiplayer.hostController.addListener('updateNetPlayers', () => {
		const arr = [];
		arr.push(MATTIE.multiplayer.hostController.player.name);
		for (key in MATTIE.multiplayer.hostController.netPlayers) {
			if (key) {
				const netPlayer = MATTIE.multiplayer.hostController.netPlayers[key];
				arr.push(netPlayer.name);
			}
		}

		this._playerWindow.updateText(arr);
	});

	this._playerWindow.updateText([MATTIE.multiplayer.hostController.player.name]);
};

MATTIE.scenes.multiplayer.host.prototype.showHideCode = function (hidden) {
	const rawPeerId = MATTIE.multiplayer.hostController.peerId;
	const encodedPeerId = rawPeerId ? btoa(rawPeerId) : null;

	const text = [
		'People can join using this number:',
		hidden && encodedPeerId
			? '*'.repeat(encodedPeerId.length)
			: (encodedPeerId || 'Error getting ID'),
	];

	if (this._peerWindow) this._peerWindow.updateText(text);
};

MATTIE.scenes.multiplayer.host.prototype.animateTick = function () {
	const text = this._peerWindow.text;
	text[1] = text[1].endsWith('...') ? text[1].replace('...', '') : `${text[1]}.`;

	if (this._peerWindow) this._peerWindow.updateText(text);

	// Ensure fallback button text matches the variable state
	this.updateFallbackButtonState();
};

MATTIE.scenes.multiplayer.host.prototype.updateFallbackButtonState = function () {
	if (!this._optionsWindow || !this._optionsWindow._mattieBtns) return;

	// Determine target state string
	const targetText = `TCP: ${MATTIE.multiplayer.forceFallback ? 'ON' : 'OFF'}`;

	// Check if backing data needs update
	let currentKey = null;
	for (const key in this._optionsWindow._mattieBtns) {
		if (this._optionsWindow._mattieBtns[key] === 'TOGGLE_FALLBACK') {
			currentKey = key;
			break;
		}
	}

	// If key is missing or different, update and refresh
	if (currentKey && currentKey !== targetText) {
		delete this._optionsWindow._mattieBtns[currentKey];
		this._optionsWindow._mattieBtns[targetText] = 'TOGGLE_FALLBACK';
		this._optionsWindow.refresh();
	}
};

MATTIE.scenes.multiplayer.host.prototype.addPeerDisplayWindow = function () {
	const text = [
		'People can join using this number:',
		'Please wait for connection to broker',
	];
	this._peerWindow = new MATTIE.windows.TextDisplay((Graphics.boxWidth - 600) / 2 + 100, 0, 600, 100, text);
	this.addWindow(this._peerWindow);
};

MATTIE.scenes.multiplayer.host.prototype.addOptionsBtns = function () {
	const btns = {};
	btns[MATTIE.TextManager.copy] = MATTIE.CmdManager.copy;
	btns[MATTIE.TextManager.startGame] = MATTIE.CmdManager.startGame;
	btns[MATTIE.TextManager.show] = MATTIE.CmdManager.show;
	btns['Close Server'] = MATTIE.CmdManager.returnToMultiplayer;

	const fallbackText = `TCP: ${MATTIE.multiplayer.forceFallback ? 'ON' : 'OFF'}`;
	btns[fallbackText] = 'TOGGLE_FALLBACK';

	this._optionsWindow = new MATTIE.windows.HorizontalBtns(175 + 300 + 10, btns, 5);
	this._optionsWindow.setHandler(MATTIE.CmdManager.startGame, (() => {
		MATTIE.multiplayer.hostController.startGame();
		MATTIE.menus.multiplayer.openGame();
	}));
	this._optionsWindow.setHandler(MATTIE.CmdManager.returnToMultiplayer, (() => {
		MATTIE.multiplayer.getCurrentNetController().destroyAllConns();
		MATTIE.multiplayer.getCurrentNetController().resetNet();
		MATTIE.menus.multiplayer.openMultiplayer();
	}));

	let hidden = true;
	this._optionsWindow.setHandler(MATTIE.CmdManager.show, (() => {
		this.showHideCode(!hidden);
		hidden = !hidden;
		this._optionsWindow.activate();
	}));

	this._optionsWindow.setHandler(MATTIE.CmdManager.copy, (() => {
		const rawPeerId = MATTIE.multiplayer.hostController.peerId;
		const encodedPeerId = rawPeerId ? btoa(rawPeerId) : 'Generating ID';
		MATTIE.clipboard.put(encodedPeerId);
		this._optionsWindow.activate();
	}));

	this._optionsWindow.setHandler('TOGGLE_FALLBACK', () => {
		const newState = !MATTIE.multiplayer.forceFallback;

		if (newState === true) {
			const ignored = MATTIE.DataManager.global.get('ignoreTCPWarning');
			if (!ignored) {
				window.alert('TCP directly reveals your ip only send this code to trusted friends.');
				const disableFuture = window.confirm('Would you like to stop seeing the TCP IP warning?');
				if (disableFuture) {
					MATTIE.DataManager.global.set('ignoreTCPWarning', true);
				}
			}
		}

		MATTIE.multiplayer.forceFallback = newState;
		MATTIE.multiplayer.userOverrideFallback = newState;

		// Immediately update button state (also handled by animateTick if running)
		this.updateFallbackButtonState();

		// Clear the displayed code immediately
		if (this._peerWindow) {
			this._peerWindow.updateText([
				'People can join using this number:',
				'Generating ID',
			]);
		}
		MATTIE.multiplayer.hostController.peerId = null;

		this._optionsWindow.activate();

		MATTIE.multiplayer.hostController.open();

		// Restart loading animation while we wait for new connection
		if (!this._loadingInterval) {
			this._loadingInterval = setInterval(() => {
				this.animateTick();
			}, 500);
		}

		this.bindToHostEvents();
	});

	this.addWindow(this._optionsWindow);
	this._optionsWindow.updateWidth(600);
	this._optionsWindow.updatePlacement(175 + 300 + 10);
};