import * as bootstrap from 'bootstrap';
import LobbyController from '../controllers/lobby-controller.js';
import ExperienceInput from './experience-input.js';
import { ReservedBuddyVariables } from 'sfs3-api';

export default class ProfileConfigurator extends HTMLElement
{
	static ONLINE_CHANGE_EVT = 'online-change';
	static BUDDY_SETTING_CHANGE_EVT = 'buddy-setting-change';
	static PLAYER_SETTING_CHANGE_EVT = 'player-setting-change';

	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" />

			<style>
				.state-label {
					font-variant-caps: all-small-caps;
				}
			</style>

			<button id="profileButton" type="button" class="btn btn-outline-primary btn-sm"><i class="fa-solid fa-user"></i></button>
			<div class="text-secondary">
				<strong class="profileNameLabel"></strong>
				<span id="stateLabel" class="state-label"></span>
			</div>
			<div class="modal" id="profileModal" tabindex="-1" aria-labelledby="profileModalLabel" aria-hidden="true">
				<div class="modal-dialog modal-dialog-centered modal-lg">
					<div class="modal-content">
						<div class="modal-header">
							<h1 class="modal-title fs-5" id="profileModalLabel">User Profile</h1>
							<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
						</div>
						 <div class="modal-body p-0">
							<div class="p-3 bg-body-tertiary">
								<strong>Name:</strong> <span class="profileNameLabel"></span>
							</div>
							<div class="p-3 border-top">
								<div class="row g-5">
									<div class="col-lg-6">
										<div class="hstack gap-3 justify-content-between">
											<h5 class="mb-0">Buddy Profile</h5>
											<div class="form-check">
												<input class="form-check-input" type="checkbox" id="profileBuddyOnline">
												<label class="form-check-label" for="profileBuddyOnline">Online</label>
											</div>
										</div>
										<hr>
										<form class="vstack gap-3">
											<div class="row">
												<label for="profileBuddyNickname" class="col-sm-3 col-form-label">Nickname</label>
												<div class="col-sm-9">
													<input type="text" class="form-control" id="profileBuddyNickname">
												</div>
											</div>
											<div class="row">
												<label for="profileBuddyState" class="col-sm-3 col-form-label">State</label>
												<div class="col-sm-9">
													<select class="form-select" id="profileBuddyState" aria-label="State"></select>
												</div>
											</div>
										</form>
									</div>
									<div class="col-lg-6">
										<h5 class="mb-0">Player Profile</h5>
										<hr>
										<form class="vstack gap-3">
											<div class="row">
												<label for="profilePlayerExp" class="col-sm-3 col-form-label">Experience</label>
												<div class="col-sm-9 align-content-center">
													<experience-input id="profilePlayerExp" value="0"></experience-input>
												</div>
											</div>
										</form>
									</div>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		`;

		this.userNameLabels = this._shadowRoot.querySelectorAll('.profileNameLabel');
		this.profileButton = this._shadowRoot.querySelector('#profileButton');
		this.stateLabel = this._shadowRoot.querySelector('#stateLabel');

		this.onlineCheck = this._shadowRoot.querySelector('#profileBuddyOnline');
		this.nicknameInput = this._shadowRoot.querySelector('#profileBuddyNickname');
		this.stateSelect = this._shadowRoot.querySelector('#profileBuddyState');

		this.experienceInput = this._shadowRoot.querySelector('#profilePlayerExp');

		// Create profile modal
		this.profileModal = new bootstrap.Modal(this._shadowRoot.querySelector('#profileModal'), {
			backdrop: true,
			focus: true,
			keyboard: true
		});

		// Bind event listeners
		this.boundOnOnlineCheckChange = this.onOnlineCheckChange.bind(this);
		this.boundOnNicknameInputBlur = this.onNicknameInputBlur.bind(this);
		this.boundOnStateSelectChange = this.onStateSelectChange.bind(this);
		this.boundOnExperienceInputChange = this.onExperienceInputChange.bind(this);
		this.boundOnProfileButtonClick = this.onProfileButtonClick.bind(this);
	}

	connectedCallback()
	{
		// Add listeners to buddy-related controls
		this.onlineCheck.addEventListener('change', this.boundOnOnlineCheckChange);
		this.nicknameInput.addEventListener('blur', this.boundOnNicknameInputBlur);
		this.stateSelect.addEventListener('change', this.boundOnStateSelectChange);

		// Add listeners to player-related controls
		this.experienceInput.addEventListener(ExperienceInput.EXPERIENCE_CHANGE_EVT, this.boundOnExperienceInputChange);

		// Add profile button click listener
		this.profileButton.addEventListener('click', this.boundOnProfileButtonClick);

		// Disable online checkbox and other controls
		// so that interaction is prevented if an error occurs during Buddy list initialization
		this.onlineCheck.disabled = true;
		this.enableBuddyControls(false);
	}

	get playerExperience()
	{
		return Number(this.experienceInput.getAttribute('value'));
	}

	displayUserName(name)
	{
		for (let userNameLabel of this.userNameLabels)
			userNameLabel.innerText = name;
	}

	displayUserState(state)
	{
		this.stateLabel.innerText = `[${state}]`;
	}

	/**
	 * Show the profile details related to the Buddy List system and add listeners.
	 */
	initBuddyProfile(sfsBuddyManager)
	{
		// User online/offline state
		this.onlineCheck.disabled = false;
		this.onlineCheck.checked = sfsBuddyManager.myOnlineState;
		this.enableBuddyControls(sfsBuddyManager.myOnlineState);

		// User nickname
		this.nicknameInput.value = (sfsBuddyManager.myNickname != null ? sfsBuddyManager.myNickname : '');

		// Available states and current user state
		while (this.stateSelect.options.length > 0)
			this.stateSelect.remove(0);

		for (let s of sfsBuddyManager.buddyStates)
		{
			const option = document.createElement('option');
			option.text = s;

			if (s == sfsBuddyManager.myState)
				option.selected = true;

			this.stateSelect.add(option);
		}
	}

	/**
	 * Show the player details (used in invitations sent from the pre-game screen).
	 */
	initPlayerProfile(user)
	{
		// User variable: experience
		this.experienceInput.setAttribute('value', user.getVariable(LobbyController.USERVAR_EXPERIENCE).value);
	}

	/**
	 * Update the state dropdown to reflect the current user state in the Buddy List system.
	 */
	updateSelectedState(state)
	{
		for (let i = 0; i < this.stateSelect.options.length; i++)
		{
			if (this.stateSelect.options[i].text == state)
			{
				this.stateSelect.selectedIndex = i;
				break;
			}
		}
	}

	enableBuddyControls(enable)
	{
		this.nicknameInput.disabled = !enable;
		this.stateSelect.disabled = !enable;
	}

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

	onProfileButtonClick(e)
	{
		this.profileModal.show();
	}

	/**
	 * Dispatch a custom event to set the user's online/offline state in the Buddy List system.
	 */
	onOnlineCheckChange(e)
	{
		const isChecked = e.currentTarget.checked;

		// Dispatch event
		this.dispatchEvent(
			new CustomEvent(ProfileConfigurator.ONLINE_CHANGE_EVT, {
				detail: {
					goOnline: isChecked
				}
			})
		);

		// Enable/disable controls
		this.enableBuddyControls(isChecked);
	}

	/**
	 * Dispatch a custom event to set the user's nickname in the Buddy List system.
	 */
	onNicknameInputBlur(e)
	{
		// Dispatch event
		this.dispatchEvent(
			new CustomEvent(ProfileConfigurator.BUDDY_SETTING_CHANGE_EVT, {
				detail: {
					variable: ReservedBuddyVariables.BV_NICKNAME,
					value: e.currentTarget.value,
				}
			})
		);
	}

	/**
	 * Dispatch a custom event to set the user's state in the Buddy List system.
	 */
	onStateSelectChange(e)
	{
		// Dispatch event
		this.dispatchEvent(
			new CustomEvent(ProfileConfigurator.BUDDY_SETTING_CHANGE_EVT, {
				detail: {
					variable: ReservedBuddyVariables.BV_STATE,
					value: e.currentTarget.value,
				}
			})
		);
	}

	/**
	 * Dispatch a custom event to set the player experience in User Variables.
	 */
	onExperienceInputChange(e)
	{
		// Dispatch event
		this.dispatchEvent(
			new CustomEvent(ProfileConfigurator.PLAYER_SETTING_CHANGE_EVT, {
				detail: {
					variable: LobbyController.USERVAR_EXPERIENCE,
					value: e.detail.experience,
				}
			})
		);
	}
}

customElements.define('profile-configurator', ProfileConfigurator);
