/**
 * A list of buddies that can be invited to join the current game.
 * Only online, available (and not blocked) buddies are added by the controller.
 */
export default class BuddyInviteList extends HTMLElement
{
	static INVITE_CLICK_EVT = 'invite-click';

	constructor()
	{
		super();

		this._shadowRoot = this.attachShadow({ mode: 'closed' });

		this._shadowRoot.innerHTML = `
			<link href="./assets/css/bootstrap.min.css" rel="stylesheet" />
			<link href="./assets/icons/css/fontawesome.min.css" rel="stylesheet" />
			<link href="./assets/icons/css/solid.min.css" rel="stylesheet" />

			<ul class="list-group list-group-flush">
				<template>
					<li class="list-group-item px-0" data-buddy-name="">
						<div class="hstack gap-3">
							<span class="flex-grow-1"><strong class="buddy-name"></strong></span>
							<button type="button" class="btn btn-primary btn-sm invite-button"><i class="fa-solid fa-gamepad"></i></button>
						</div>
					</li>
				</template>
			</ul>
			<div class="empty-msg text-body-secondary fst-italic py-3">No buddies available to invite.</div>
		`;

		this.list = this._shadowRoot.querySelector('ul');
		this.emptyMsg = this._shadowRoot.querySelector('.empty-msg');

		this.boundOnInviteButtonClick = this.onInviteButtonClick.bind(this);
	}

	connectedCallback()
	{
		this.updateEmptyMsg();
	}

	reset()
	{
		for (let item of this.list.querySelectorAll('li[data-buddy-name]'))
			this.removeItem(item.dataset.buddyName);
	}

	getItem(buddyName)
	{
		return this.list.querySelector(`li[data-buddy-name="${buddyName}"]`);
	}

	hasItem(buddyName)
	{
		return this.getItem(buddyName) != null;
	}

	addItem(buddyName, displayName)
	{
		if (this.hasItem(buddyName))
			return;

		// Create item from template
		const template = this.list.querySelector('template');
		const node = template.content.cloneNode(true);
		node.firstElementChild.dataset.buddyName = buddyName;

		this.list.append(node);

		// Set label and listener
		const item = this.getItem(buddyName);
		item.querySelector('.buddy-name').innerText = displayName;
		item.querySelector('.invite-button').addEventListener('click', this.boundOnInviteButtonClick);

		this.updateEmptyMsg();
	}

	removeItem(buddyName)
	{
		const item = this.getItem(buddyName);

		if (item != null)
		{
			item.querySelector('.invite-button').removeEventListener('click', this.boundOnInviteButtonClick);
			this.list.removeChild(item);
		}

		this.updateEmptyMsg();
	}

	disableItem(buddyName)
	{
		const item = this.getItem(buddyName);

		if (item != null)
			item.querySelector('.invite-button').disabled = true;
	}

	updateEmptyMsg()
	{
		this.emptyMsg.hidden = this.list.querySelectorAll('li[data-buddy-name]').length > 0;
	}

	/**
	 * Whether there is at least one buddy that can still be invited (invite button not disabled).
	 */
	hasEnabledItems()
	{
		return this.list.querySelector('li[data-buddy-name] .invite-button:not([disabled])') != null;
	}

	onInviteButtonClick(e)
	{
		const buddyName = e.currentTarget.closest('li').dataset.buddyName;

		// Disable the button to prevent multiple invitations
		e.currentTarget.disabled = true;

		this.dispatchEvent(
			new CustomEvent(BuddyInviteList.INVITE_CLICK_EVT, {
				detail: {
					buddyName: buddyName
				}
			})
		);
	}
}

customElements.define('buddy-invite-list', BuddyInviteList);
