<!--
  - @copyright Copyright (c) 2024 Ferdinand Thiessen <opensource@fthiessen.de>
  -
  - @author Ferdinand Thiessen <opensource@fthiessen.de>
  -
  - @license AGPL-3.0-or-later
  -
  - This program is free software: you can redistribute it and/or modify
  - it under the terms of the GNU Affero General Public License as
  - published by the Free Software Foundation, either version 3 of the
  - License, or (at your option) any later version.
  -
  - This program is distributed in the hope that it will be useful,
  - but WITHOUT ANY WARRANTY; without even the implied warranty of
  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  - GNU Affero General Public License for more details.
  -
  - You should have received a copy of the GNU Affero General Public License
  - along with this program. If not, see <http://www.gnu.org/licenses/>.
  -
  -->
<template>
	<a v-if="linkProps" v-bind="linkProps">
		<slot />
	</a>
	<RouterLink v-else-if="routerProps" v-bind="routerProps">
		<slot />
	</RouterLink>
</template>

<script lang="ts">
import type { RouterLinkProps } from 'vue-router/types/router.js'

import { loadState } from '@nextcloud/initial-state'
import { generateUrl } from '@nextcloud/router'
import { defineComponent } from 'vue'
import { RouterLink } from 'vue-router'

const knownRoutes = Object.fromEntries(
	Object.entries(
		loadState<Record<string, { app?: string, href: string }>>('core', 'apps'),
	).map(([k, v]) => [v.app ?? k, v.href]),
)

/**
 * This component either shows a native link to the installed app or external size - or a router link to the appstore page of the app if not installed
 */
export default defineComponent({
	name: 'AppLink',

	components: { RouterLink },

	props: {
		href: {
			type: String,
			required: true,
		},
	},

	data() {
		return {
			routerProps: undefined as RouterLinkProps|undefined,
			linkProps: undefined as Record<string, string>|undefined,
		}
	},

	watch: {
		href: {
			immediate: true,
			handler() {
				const match = this.href.match(/^app:\/\/([^/]+)(\/.+)?$/)
				this.routerProps = undefined
				this.linkProps = undefined

				// not an app url
				if (match === null) {
					this.linkProps = {
						href: this.href,
						target: '_blank',
						rel: 'noreferrer noopener',
					}
					return
				}

				const appId = match[1]
				// Check if specific route was requested
				if (match[2]) {
					// we do no know anything about app internal path so we only allow generic app paths
					this.linkProps = {
						href: generateUrl(`/apps/${appId}${match[2]}`),
					}
					return
				}

				// If we know any route for that app we open it
				if (appId in knownRoutes) {
					this.linkProps = {
						href: knownRoutes[appId],
					}
					return
				}

				// Fallback to show the app store entry
				this.routerProps = {
					to: {
						name: 'apps-details',
						params: {
							category: this.$route.params?.category ?? 'discover',
							id: appId,
						},
					},
				}
			},
		},
	},
})
</script>
