<!--
  - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
  -
  - @author Julius Härtl <jus@bitgrid.net>
  -
  - @license GNU AGPL version 3 or any later version
  -
  - 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>
	<div id="app-details-view" style="padding: 20px;">
		<h2>
			<div v-if="!app.preview" class="icon-settings-dark" />
			<svg v-if="app.previewAsIcon && app.preview"
				width="32"
				height="32"
				viewBox="0 0 32 32">
				<defs><filter :id="filterId"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" /></filter></defs>
				<image x="0"
					y="0"
					width="32"
					height="32"
					preserveAspectRatio="xMinYMin meet"
					:filter="filterUrl"
					:xlink:href="app.preview"
					class="app-icon" />
			</svg>
			{{ app.name }}
		</h2>
		<img v-if="screenshotLoaded" :src="app.screenshot" width="100%">
		<div v-if="app.level === 300 || app.level === 200 || hasRating" class="app-level">
			<span v-if="app.level === 300"
				v-tooltip.auto="t('settings', 'This app is supported via your current Nextcloud subscription.')"
				class="supported icon-checkmark-color">
				{{ t('settings', 'Supported') }}</span>
			<span v-if="app.level === 200"
				v-tooltip.auto="t('settings', 'Featured apps are developed by and within the community. They offer central functionality and are ready for production use.')"
				class="official icon-checkmark">
				{{ t('settings', 'Featured') }}</span>
			<AppScore v-if="hasRating" :score="app.appstoreData.ratingOverall" />
		</div>

		<div v-if="author" class="app-author">
			{{ t('settings', 'by') }}
			<span v-for="(a, index) in author" :key="index">
				<a v-if="a['@attributes'] && a['@attributes']['homepage']" :href="a['@attributes']['homepage']">{{ a['@value'] }}</a><span v-else-if="a['@value']">{{ a['@value'] }}</span><span v-else>{{ a }}</span><span v-if="index+1 < author.length">, </span>
			</span>
		</div>
		<div v-if="licence" class="app-licence">
			{{ licence }}
		</div>
		<div class="actions">
			<div class="actions-buttons">
				<input v-if="app.update"
					class="update primary"
					type="button"
					:value="t('settings', 'Update to {version}', {version: app.update})"
					:disabled="installing || loading(app.id)"
					@click="update(app.id)">
				<input v-if="app.canUnInstall"
					class="uninstall"
					type="button"
					:value="t('settings', 'Remove')"
					:disabled="installing || loading(app.id)"
					@click="remove(app.id)">
				<input v-if="app.active"
					class="enable"
					type="button"
					:value="t('settings','Disable')"
					:disabled="installing || loading(app.id)"
					@click="disable(app.id)">
				<input v-if="!app.active && (app.canInstall || app.isCompatible)"
					v-tooltip.auto="enableButtonTooltip"
					class="enable primary"
					type="button"
					:value="enableButtonText"
					:disabled="!app.canInstall || installing || loading(app.id)"
					@click="enable(app.id)">
				<input v-else-if="!app.active"
					v-tooltip.auto="forceEnableButtonTooltip"
					class="enable force"
					type="button"
					:value="forceEnableButtonText"
					:disabled="installing || loading(app.id)"
					@click="forceEnable(app.id)">
			</div>
			<div class="app-groups">
				<div v-if="app.active && canLimitToGroups(app)" class="groups-enable">
					<input :id="prefix('groups_enable', app.id)"
						v-model="groupCheckedAppsData"
						type="checkbox"
						:value="app.id"
						class="groups-enable__checkbox checkbox"
						@change="setGroupLimit">
					<label :for="prefix('groups_enable', app.id)">{{ t('settings', 'Limit to groups') }}</label>
					<input type="hidden"
						class="group_select"
						:title="t('settings', 'All')"
						value="">
					<Multiselect v-if="isLimitedToGroups(app)"
						:options="groups"
						:value="appGroups"
						:options-limit="5"
						:placeholder="t('settings', 'Limit app usage to groups')"
						label="name"
						track-by="id"
						class="multiselect-vue"
						:multiple="true"
						:close-on-select="false"
						:tag-width="60"
						@select="addGroupLimitation"
						@remove="removeGroupLimitation"
						@search-change="asyncFindGroup">
						<span slot="noResult">{{ t('settings', 'No results') }}</span>
					</Multiselect>
				</div>
			</div>
		</div>

		<ul class="app-dependencies">
			<li v-if="app.missingMinOwnCloudVersion">
				{{ t('settings', 'This app has no minimum Nextcloud version assigned. This will be an error in the future.') }}
			</li>
			<li v-if="app.missingMaxOwnCloudVersion">
				{{ t('settings', 'This app has no maximum Nextcloud version assigned. This will be an error in the future.') }}
			</li>
			<li v-if="!app.canInstall">
				{{ t('settings', 'This app cannot be installed because the following dependencies are not fulfilled:') }}
				<ul class="missing-dependencies">
					<li v-for="(dep, index) in app.missingDependencies" :key="index">
						{{ dep }}
					</li>
				</ul>
			</li>
		</ul>

		<p class="documentation">
			<a v-if="!app.internal"
				class="appslink"
				:href="appstoreUrl"
				target="_blank"
				rel="noreferrer noopener">{{ t('settings', 'View in store') }} ↗</a>

			<a v-if="app.website"
				class="appslink"
				:href="app.website"
				target="_blank"
				rel="noreferrer noopener">{{ t('settings', 'Visit website') }} ↗</a>
			<a v-if="app.bugs"
				class="appslink"
				:href="app.bugs"
				target="_blank"
				rel="noreferrer noopener">{{ t('settings', 'Report a bug') }} ↗</a>

			<a v-if="app.documentation && app.documentation.user"
				class="appslink"
				:href="app.documentation.user"
				target="_blank"
				rel="noreferrer noopener">{{ t('settings', 'User documentation') }} ↗</a>
			<a v-if="app.documentation && app.documentation.admin"
				class="appslink"
				:href="app.documentation.admin"
				target="_blank"
				rel="noreferrer noopener">{{ t('settings', 'Admin documentation') }} ↗</a>
			<a v-if="app.documentation && app.documentation.developer"
				class="appslink"
				:href="app.documentation.developer"
				target="_blank"
				rel="noreferrer noopener">{{ t('settings', 'Developer documentation') }} ↗</a>
		</p>

		<div class="app-description" v-html="renderMarkdown" />
	</div>
</template>

<script>
import { Multiselect } from '@nextcloud/vue'
import marked from 'marked'
import dompurify from 'dompurify'

import AppScore from './AppList/AppScore'
import AppManagement from './AppManagement'
import PrefixMixin from './PrefixMixin'
import SvgFilterMixin from './SvgFilterMixin'

export default {
	name: 'AppDetails',
	components: {
		Multiselect,
		AppScore,
	},
	mixins: [AppManagement, PrefixMixin, SvgFilterMixin],
	props: ['category', 'app'],
	data() {
		return {
			groupCheckedAppsData: false,
			screenshotLoaded: false,
		}
	},
	computed: {
		appstoreUrl() {
			return `https://apps.nextcloud.com/apps/${this.app.id}`
		},
		licence() {
			if (this.app.licence) {
				return t('settings', '{license}-licensed', { license: ('' + this.app.licence).toUpperCase() })
			}
			return null
		},
		hasRating() {
			return this.app.appstoreData && this.app.appstoreData.ratingNumOverall > 5
		},
		author() {
			if (typeof this.app.author === 'string') {
				return [
					{
						'@value': this.app.author,
					},
				]
			}
			if (this.app.author['@value']) {
				return [this.app.author]
			}
			return this.app.author
		},
		appGroups() {
			return this.app.groups.map(group => { return { id: group, name: group } })
		},
		groups() {
			return this.$store.getters.getGroups
				.filter(group => group.id !== 'disabled')
				.sort((a, b) => a.name.localeCompare(b.name))
		},
		renderMarkdown() {
			const renderer = new marked.Renderer()
			renderer.link = function(href, title, text) {
				let prot
				try {
					prot = decodeURIComponent(unescape(href))
						.replace(/[^\w:]/g, '')
						.toLowerCase()
				} catch (e) {
					return ''
				}

				if (prot.indexOf('http:') !== 0 && prot.indexOf('https:') !== 0) {
					return ''
				}

				let out = '<a href="' + href + '" rel="noreferrer noopener"'
				if (title) {
					out += ' title="' + title + '"'
				}
				out += '>' + text + '</a>'
				return out
			}
			renderer.image = function(href, title, text) {
				if (text) {
					return text
				}
				return title
			}
			renderer.blockquote = function(quote) {
				return quote
			}
			return dompurify.sanitize(
				marked(this.app.description.trim(), {
					renderer: renderer,
					gfm: false,
					highlight: false,
					tables: false,
					breaks: false,
					pedantic: false,
					sanitize: true,
					smartLists: true,
					smartypants: false,
				}),
				{
					SAFE_FOR_JQUERY: true,
					ALLOWED_TAGS: [
						'strong',
						'p',
						'a',
						'ul',
						'ol',
						'li',
						'em',
						'del',
						'blockquote',
					],
				}
			)
		},
	},
	mounted() {
		if (this.app.groups.length > 0) {
			this.groupCheckedAppsData = true
		}
		if (this.app.screenshot) {
			const image = new Image()
			image.onload = (e) => {
				this.screenshotLoaded = true
			}
			image.src = this.app.screenshot
		}
	},
}
</script>

<style scoped>
	.force {
		background: var(--color-main-background);
		border-color: var(--color-error);
		color: var(--color-error);
	}
	.force:hover,
	.force:active {
		background: var(--color-error);
		border-color: var(--color-error) !important;
		color: var(--color-main-background);
	}
</style>
