// Create a new WebSocket connection.
// Note that window.location.host contains both the host and the port,
// so we only need to prefix with the correct protocol.

const protocol = (window.location.protocol === 'https:') ? 'wss://' : 'ws://';
const wsURL = protocol + window.location.host;
let socket;

console.log(wsURL);

function connect()
{
	// Create and open a new socket to the server
	
	socket = new WebSocket(wsURL);

	socket.addEventListener('open', function (event)
	{
		console.log('✅ WebSocket connected');
	});

	// When a message is received from the server, unpack the JSON dictionary and update the correct DOM element

	socket.addEventListener('message', function (event)
	{
		const data = JSON.parse(event.data);

		if (data.command === 'setInnerHTML')
		{
			setInnerHTML(data.id, data.value);
		}
		else if (data.command === 'setWidth')
		{
			setWidth(data.id, data.value);
		}
		else if (data.command === 'setEnabled')
		{
			setEnabled(data.id, data.value);
		}
		else if (data.command === 'addClass')
		{
			addClass(data.id, data.value);
		}
		else if (data.command === 'removeClass')
		{
			removeClass(data.id, data.value);
		}
		else if (data.command === 'makePrimary')
		{
			makePrimary(data.id);
		}
		else if (data.command === 'scrollTo')
		{
			scrollToElementWithId(data.id);
		}
		else if (data.command === 'selectChapter')
		{
			selectChapter(data.id);
		}
		else if (data.command === 'updateSliderValue')
		{
			updateSliderValue(data.id,data.value)
		}
		else if (data.command === 'reload')
		{
			window.location.reload();
		}
	});
	
	// When we get an error, close the socket and try to re-connect with a new socket after 1s
	
	socket.addEventListener('error', function (err)
	{
		console.error('❌ WebSocket error:', err);
		socket.close(); // ensure 'close' gets triggered
	});

	socket.addEventListener('close', function (event)
	{
		console.log('⚠️ WebSocket closed. Retrying in 1s...');
		setTimeout(connect, 1000); // retry after 1 second
	});
}

// Initial connection to server

connect();


// Close any open popups when clicking on the background

document.getElementsByTagName('body')[0].onclick = function()
{
    closeAllPopups();
}


// Install event handlers for the volume slider

const slider = document.getElementById('volumeSlider');

if (slider)
{
    slider.addEventListener('input', function(event)
    {
        sendSliderValue('volumeSlider');
    });
    
    slider.addEventListener('click', function(event)
    {
        event.stopPropagation();    // Make sure that event doesn't close popup (see onclick installed on body)
    });
}


//----------------------------------------------------------------------------------------------------------------------


// HELPERS


// Sends a string based message to the server

function sendMessage(string)
{
	socket.send(string);
}


// Replaces the inner HTML of the element with the specified id

function setInnerHTML(id,html)
{
	const element = document.getElementById(id);
	
	if (element)
	{
		element.innerHTML = html;
	}
}


// Closes all popup that are currently open

function closeAllPopups()
{
	const allPopups = document.getElementsByClassName("popup");
	
	if (allPopups)
	{
		Array.from(allPopups).forEach( function (popup)
		{
			popup.classList.remove("open");
		});
	}
}


// Toggles the open state of the popup with the specified id

function togglePopup(id)
{
	const popup = document.getElementById(id);
	
	if (popup)
	{
		if (popup.classList.contains("open"))
		{
			popup.classList.remove("open");
		}
		else
		{
			setTimeout(function(){ popup.classList.add("open") }, 5);
		}
	}
}


// Enables or disables the element with the specified id. This is useful for buttons or menu items.

function setEnabled(id,value)
{
	const button = document.getElementById(id);
	
	if (button)
	{
		button.classList.remove("enabled");
		button.classList.remove("disabled");

		if (value == "false")
		{
			button.classList.add("disabled")
		}
	}
}


// Call this function in onlick of a menu item element

function clickMenuItem(id,action)
{
	const menuItem = document.getElementById(id);
	if (menuItem && !menuItem.classList.contains('disabled'))
	{
		action();
		setTimeout(closeAllPopups,500);
	}
}


// Call this function in onlick of a button element

function clickButton(id,action)
{
	const button = document.getElementById(id);
	
	if (button && !button.classList.contains("disabled"))
	{
		button.classList.add("pressed");
		action();
		setTimeout(function(){ button.classList.remove("pressed") }, 200);
	}
}


// Call this function in onlick of the volume slider

function sendSliderValue(id)
{
	const slider = document.getElementById(id);
	
	if (slider)
	{
		const value = slider.value;
		const message = id + "=" + value;
		sendMessage(message);
	}
}

function updateSliderValue(id,value)
{
	const slider = document.getElementById(id);
	
	if (slider)
	{
		slider.value = value
	}
}

// Adds a checkmark to the chapter menu item with the specified id

function selectChapter(id)
{
	const menuItems = document.querySelectorAll(".popup-menu-item.chapter");
	
	if (menuItems)
	{
		Array.from(menuItems).forEach( function (menuItem)
		{
			menuItem.classList.remove("checkmark");
		});
	}

	const menuItem = document.getElementById(id);
	if (menuItem) { menuItem.classList.add("checkmark"); }
}


// Set the width of the element with the specified id

function setWidth(id,width)
{
	const element = document.querySelectorAll(id)[0];
	
	if (element)
	{
		element.style.width = width;
	}
}


// Add or remove a class from the element with the specified id

function addClass(id,className)
{
	const element = document.getElementById(id);
	
	if (element)
	{
		element.classList.add(className);
	}
}

function removeClass(id,className)
{
	const element = document.getElementById(id);
	
	if (element)
	{
		element.classList.remove(className);
	}
}


// Scrolls the teleprompter so that the element with the specified id appears at the top

var lastScrollID = "";

function scrollToElementWithId(id)
{
	const teleprompter = document.getElementById('teleprompter');
	const slide = document.getElementById(id);
	const offset = 20;
	
	if (teleprompter && slide && lastScrollID != id)
	{
		teleprompter.scrollTo(
		{
			top: slide.offsetTop - teleprompter.offsetTop - offset,
			behavior: 'smooth' // Optional: Adds smooth scrolling
		});
		
		lastScrollID = id
	}
}
   
   
// Reloads the web page

function reload()
{
	window.location.reload();
}

// Hilites the slide element with the specified id. All other slide elements are gray out.

function makePrimary(id)
{
	const oldElements = document.getElementsByClassName("slide primary");
	
	if (oldElements)
	{
		Array.from(oldElements).forEach( function (oldElement)
		{
			oldElement.className = "slide secondary";
		});
	}
	
	const element = document.getElementById(id);

	if (element)
	{
		element.className = "slide primary";
	}
}


// Logs a message to the console

function log(message)
{
	console.log(message);
}


//----------------------------------------------------------------------------------------------------------------------
