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

<template>
	<div v-if="isVisible" class="widgets--list" :class="{ 'icon-loading': loading }">
		<NcReferenceWidget
			v-for="reference in displayedReferences"
			:key="reference.openGraphObject?.id"
			:reference="reference"
			:interactive="interactive"
			:interactiveOptIn="interactiveOptIn" />
	</div>
</template>

<script>
import { getCurrentUser } from '@nextcloud/auth'
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
import { getSharingToken } from '@nextcloud/sharing/public'
import NcReferenceWidget from './NcReferenceWidget.vue'
import { logger } from '../../utils/logger.ts'
import { URL_PATTERN } from './helpers.js'

export default {
	name: 'NcReferenceList',
	components: {
		NcReferenceWidget,
	},

	props: {
		/**
		 * The text to extract references from
		 */
		text: {
			type: String,
			default: '',
		},

		/**
		 * The data of the references to display.
		 */
		referenceData: {
			type: Array,
			default: null,
		},

		/**
		 * The maximum number of references to display
		 */
		limit: {
			type: Number,
			default: 1,
		},

		/**
		 * Show the fallback reference if no references are found
		 */
		displayFallback: {
			type: Boolean,
			default: false,
		},

		/**
		 * Whether to render the widgets in interactive mode (if available)
		 */
		interactive: {
			type: Boolean,
			default: true,
		},

		/**
		 * Whether to show user an option to enable to interactive mode for widgets (if available)
		 */
		interactiveOptIn: {
			type: Boolean,
			default: false,
		},
	},

	emits: ['loaded'],
	data() {
		return {
			references: null,
			loading: true,
		}
	},

	computed: {
		isVisible() {
			return this.loading || this.displayedReferences.length !== 0
		},

		values() {
			if (this.referenceData) {
				return this.referenceData
			}

			if (this.displayFallback && !this.loading && !this.references) {
				return [this.fallbackReference]
			}

			return this.references ? Object.values(this.references) : []
		},

		firstReference() {
			return this.values[0] ?? null
		},

		displayedReferences() {
			return this.values.filter(Boolean).slice(0, this.limit)
		},

		fallbackReference() {
			return {
				accessible: true,
				openGraphObject: {
					id: this.text,
					link: this.text,
					name: this.text,
				},

				richObjectType: 'open-graph',
			}
		},
	},

	watch: {
		text: 'fetch',
	},

	mounted() {
		this.fetch()
	},

	methods: {
		fetch() {
			this.loading = true
			if (this.referenceData) {
				this.references = null
				this.loading = false
				return
			}

			if (!(new RegExp(URL_PATTERN).exec(this.text))) {
				this.references = null
				this.loading = false
				return
			}

			this.resolve().then((response) => {
				this.references = response.data.ocs.data.references
				this.loading = false
				this.$emit('loaded')
			}).catch((error) => {
				logger.error('[NcReferenceList] Failed to extract references', { error })
				this.loading = false
				this.$emit('loaded')
			})
		},

		resolve() {
			const match = (new RegExp(URL_PATTERN).exec(this.text.trim()))
			const isPublic = getCurrentUser() === null
			if (this.limit === 1 && match) {
				return isPublic
					? axios.get(generateOcsUrl('references/resolvePublic') + `?reference=${encodeURIComponent(match[0])}&sharingToken=${getSharingToken()}`)
					: axios.get(generateOcsUrl('references/resolve') + `?reference=${encodeURIComponent(match[0])}`)
			}

			return isPublic
				? axios.post(generateOcsUrl('references/extractPublic'), {
						text: this.text,
						resolve: true,
						limit: this.limit,
						sharingToken: getSharingToken(),
					})
				: axios.post(generateOcsUrl('references/extract'), {
						text: this.text,
						resolve: true,
						limit: this.limit,
					})
		},
	},
}
</script>

<style lang="scss" scoped>
.widgets--list {
	width: 100%;
	min-height: var(--default-clickable-area);
}
</style>
