<!--
  - SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
  - SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
	<div class="username-form">
		<!-- eslint-disable-next-line vue/no-v-html -->
		<h3 v-if="!compact" v-html="displayNameLabel" />

		<NcButton
			v-if="!isEditingUsername && !compact"
			@click="toggleEdit">
			{{ t('spreed', 'Edit display name') }}
			<template #icon>
				<IconPencilOutline :size="20" />
			</template>
		</NcButton>

		<div v-else class="username-form__display-name">
			<IconAccountOutline class="username-form__display-name-icon" :size="20" />
			<NcTextField
				ref="usernameInput"
				v-model="guestUserName"
				:placeholder="t('spreed', 'Guest')"
				class="username-form__input"
				:label="t('spreed', 'Display name (required)')"
				:show-trailing-button="!!guestUserName && !compact"
				trailing-button-icon="arrowEnd"
				:trailing-button-label="t('spreed', 'Save name')"
				@trailing-button-click="!compact ? updateDisplayName() : null"
				@keydown.enter="!compact ? updateDisplayName() : null"
				@keydown.esc="toggleEdit" />
		</div>

		<div class="login-info">
			<span> {{ t('spreed', 'Do you already have an account?') }}</span>
			<NcButton
				class="login-info__button"
				variant="secondary"
				:href="loginUrl">
				{{ t('spreed', 'Log in') }}
			</NcButton>
		</div>
	</div>
</template>

<script setup lang="ts">
import type { NextcloudUser } from '@nextcloud/auth'

import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { t } from '@nextcloud/l10n'
import { generateUrl } from '@nextcloud/router'
import debounce from 'debounce'
import escapeHtml from 'escape-html'
import { computed, nextTick, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'
import NcButton from '@nextcloud/vue/components/NcButton'
import NcTextField from '@nextcloud/vue/components/NcTextField'
import IconAccountOutline from 'vue-material-design-icons/AccountOutline.vue'
import IconPencilOutline from 'vue-material-design-icons/PencilOutline.vue'
import { useGetToken } from '../composables/useGetToken.ts'
import { EventBus } from '../services/EventBus.ts'
import { useActorStore } from '../stores/actor.ts'
import { useGuestNameStore } from '../stores/guestName.ts'

const { compact = false } = defineProps<{
	compact?: boolean
}>()

const loginUrl = `${generateUrl('/login')}?redirect_url=${encodeURIComponent(window.location.pathname)}`

const actorStore = useActorStore()
const guestNameStore = useGuestNameStore()
const token = useGetToken()

const usernameInput = useTemplateRef('usernameInput')

const guestUserName = computed({
	get: () => guestNameStore.guestUserName,
	set: (newValue: string) => {
		guestNameStore.guestUserName = newValue
		debounceUpdateDisplayName()
	},
})
const isEditingUsername = ref(false)

const actorDisplayName = computed<string>(() => actorStore.displayName || guestUserName.value)
const displayNameLabel = computed(() => t('spreed', 'Display name: {name}', {
	name: `<strong>${escapeHtml(actorDisplayName.value)}</strong>`,
}, { escape: false }))
const debounceUpdateDisplayName = debounce(updateDisplayName, 10_000)

watch(actorDisplayName, (newValue) => {
	if (newValue && newValue !== guestUserName.value) {
		guestUserName.value = newValue
	}
})

/** Initially set displayName in store, if available from BrowserStorage */
let delayUpdateDisplayName = false
if (guestUserName.value && !actorStore.displayName) {
	actorStore.setDisplayName(guestUserName.value)
	delayUpdateDisplayName = true
}

/** Update guest displayName for other attendees */
EventBus.once('joined-conversation', () => {
	if (guestUserName.value && delayUpdateDisplayName) {
		console.debug('Saving guest name from browser storage to the session')
		updateDisplayName()
	}
})

/** Update guest displayName from public event (e.g. `@nextcloud/auth`) */
subscribe('user:info:changed', updateDisplayNameFromPublicEvent)
onBeforeUnmount(() => {
	unsubscribe('user:info:changed', updateDisplayNameFromPublicEvent)
	debounceUpdateDisplayName.flush?.()
})

/**
 * Update guest username from public page user menu
 *
 * @param payload
 */
function updateDisplayNameFromPublicEvent(payload: NextcloudUser) {
	if (payload.displayName && payload.displayName !== guestUserName.value) {
		guestUserName.value = payload.displayName
		updateDisplayName()
	}
}

/** Set guest username locally and send request to server to update for other attendees */
function updateDisplayName() {
	if (!guestUserName.value) {
		return
	}
	guestNameStore.submitGuestUsername(token.value, guestUserName.value)
	isEditingUsername.value = false
}

/** Toggle editing state of username */
function toggleEdit() {
	isEditingUsername.value = !isEditingUsername.value
	if (isEditingUsername.value) {
		nextTick(() => {
			usernameInput.value!.focus()
		})
	}
}
</script>

<style lang="scss" scoped>
.username-form {

	&__display-name {
		display: flex;
		gap: var(--default-grid-baseline);
		flex-direction: row;
		margin-block-start: 6px; // moved from NcTextField

		&-icon {
			flex-shrink: 0;
			margin-inline-end: var(--default-grid-baseline);
		}
	}
}

.login-info {
	display: flex;
	align-items: center;
	gap: calc(var(--default-grid-baseline) * 2);
	padding: calc(var(--default-grid-baseline) * 2) calc(var(--default-grid-baseline) * 2) 0;
	margin-inline-start: calc(var(--default-grid-baseline) + 20px); // 20px for checkbox alignment

	&__button {
		flex-shrink: 0;
	}
}

:deep(.input-field) {
	margin-block-start: 0;
}

</style>
