<template>
	<create-edit
		:title="$t('list.background.title')"
		primary-label=""
		:loading="backgroundService.loading"
		class="list-background-setting"
		:wide="true"
		v-if="uploadBackgroundEnabled || unsplashBackgroundEnabled"
		:tertiary="hasBackground ? $t('list.background.remove') : ''"
		@tertiary="removeBackground()"
	>
		<div class="mb-4" v-if="uploadBackgroundEnabled">
			<input
				@change="uploadBackground"
				accept="image/*"
				class="is-hidden"
				ref="backgroundUploadInput"
				type="file"
			/>
			<x-button
				:loading="backgroundUploadService.loading"
				@click="$refs.backgroundUploadInput.click()"
				variant="primary"
			>
				{{ $t('list.background.upload') }}
			</x-button>
		</div>
		<template v-if="unsplashBackgroundEnabled">
			<input
				:class="{'is-loading': backgroundService.loading}"
				@keyup="() => debounceNewBackgroundSearch()"
				class="input is-expanded"
				:placeholder="$t('list.background.searchPlaceholder')"
				type="text"
				v-model="backgroundSearchTerm"
			/>
			<p class="unsplash-link">
				<a href="https://unsplash.com" rel="noreferrer noopener nofollow" target="_blank">
					{{ $t('list.background.poweredByUnsplash') }}
				</a>
			</p>
			<div class="image-search-result">
				<a
					:key="im.id"
					:style="{'background-image': `url(${backgroundBlurHashes[im.id]})`}"
					@click="() => setBackground(im.id)"
					class="image"
					v-for="im in backgroundSearchResult">
					<transition name="fade">
						<img :src="backgroundThumbs[im.id]" alt="" v-if="backgroundThumbs[im.id]"/>
					</transition>
					<a
						:href="`https://unsplash.com/@${im.info.author}`"
						rel="noreferrer noopener nofollow"
						target="_blank"
						class="info">
						{{ im.info.authorName }}
					</a>
				</a>
			</div>
			<x-button
				:disabled="backgroundService.loading"
				@click="() => searchBackgrounds(currentPage + 1)"
				class="is-load-more-button mt-4"
				:shadow="false"
				variant="secondary"
				v-if="backgroundSearchResult.length > 0"
			>
				{{ backgroundService.loading ? $t('misc.loading') : $t('list.background.loadMore') }}
			</x-button>
		</template>
	</create-edit>
</template>

<script lang="ts">
import {mapState} from 'vuex'
import {getBlobFromBlurHash} from '../../../helpers/getBlobFromBlurHash'

import BackgroundUnsplashService from '../../../services/backgroundUnsplash'
import BackgroundUploadService from '../../../services/backgroundUpload'
import ListService from '@/services/list'
import {CURRENT_LIST} from '@/store/mutation-types'
import CreateEdit from '@/components/misc/create-edit.vue'
import debounce from 'lodash.debounce'

const SEARCH_DEBOUNCE = 300

export default {
	name: 'list-setting-background',
	components: {CreateEdit},
	data() {
		return {
			backgroundService: new BackgroundUnsplashService(),
			backgroundSearchTerm: '',
			backgroundSearchResult: [],
			backgroundThumbs: {},
			backgroundBlurHashes: {},
			currentPage: 1,

			// We're using debounce to not search on every keypress but with a delay.
			debounceNewBackgroundSearch: debounce(this.newBackgroundSearch, SEARCH_DEBOUNCE, {
				trailing: true,
			}),

			backgroundUploadService: new BackgroundUploadService(),
			listService: new ListService(),
		}
	},
	computed: mapState({
		unsplashBackgroundEnabled: state => state.config.enabledBackgroundProviders.includes('unsplash'),
		uploadBackgroundEnabled: state => state.config.enabledBackgroundProviders.includes('upload'),
		currentList: state => state.currentList,
		hasBackground: state => state.background !== null,
	}),
	created() {
		this.setTitle(this.$t('list.background.title'))
		// Show the default collection of backgrounds
		this.newBackgroundSearch()
	},
	methods: {
		newBackgroundSearch() {
			if (!this.unsplashBackgroundEnabled) {
				return
			}
			// This is an extra method to reset a few things when searching to not break loading more photos.
			this.backgroundSearchResult = []
			this.backgroundThumbs = {}
			this.searchBackgrounds()
		},

		async searchBackgrounds(page = 1) {
			this.currentPage = page
			const result = await this.backgroundService.getAll({}, {s: this.backgroundSearchTerm, p: page})
			this.backgroundSearchResult = this.backgroundSearchResult.concat(result)
			result.forEach(background => {
				getBlobFromBlurHash(background.blurHash)
					.then(b => {
						this.backgroundBlurHashes[background.id] = window.URL.createObjectURL(b)
					})

				this.backgroundService.thumb(background)
					.then(b => {
						this.backgroundThumbs[background.id] = b
					})
			})
		},

		async setBackground(backgroundId) {
			// Don't set a background if we're in the process of setting one
			if (this.backgroundService.loading) {
				return
			}

			const list = await this.backgroundService.update({id: backgroundId, listId: this.$route.params.listId})
			await this.$store.dispatch(CURRENT_LIST, list)
			this.$store.commit('namespaces/setListInNamespaceById', list)
			this.$store.commit('lists/setList', list)
			this.$message.success({message: this.$t('list.background.success')})
		},

		async uploadBackground() {
			if (this.$refs.backgroundUploadInput.files.length === 0) {
				return
			}

			const list = await this.backgroundUploadService.create(this.$route.params.listId, this.$refs.backgroundUploadInput.files[0])
			await this.$store.dispatch(CURRENT_LIST, list)
			this.$store.commit('namespaces/setListInNamespaceById', list)
			this.$store.commit('lists/setList', list)
			this.$message.success({message: this.$t('list.background.success')})
		},

		async removeBackground() {
			const list = await this.listService.removeBackground(this.currentList)
			await this.$store.dispatch(CURRENT_LIST, list)
			this.$store.commit('namespaces/setListInNamespaceById', list)
			this.$store.commit('lists/setList', list)
			this.$message.success({message: this.$t('list.background.removeSuccess')})
			this.$router.back()
		},
	},
}
</script>

<style lang="scss" scoped>
.list-background-setting {

	.unsplash-link {
		text-align: right;
		font-size: .8rem;

		a {
			color: var(--grey-800);
		}
	}

	.image-search-result {
		margin-top: 1rem;
		display: flex;
		flex-flow: row wrap;

		.image {
			width: calc(100% / 5 - 1rem);
			height: 120px;
			margin: .5rem;
			background-size: cover;
			background-position: center;
			display: flex;
			position: relative;

			@media screen and (min-width: $desktop) {
				&:nth-child(5n) {
					break-after: always;
				}
			}

			@media screen and (max-width: $desktop) {
				width: calc(100% / 4 - 1rem);

				&:nth-child(4n) {
					break-after: always;
				}
			}

			@media screen and (max-width: $tablet) {
				width: calc(100% / 2 - 1rem);

				&:nth-child(2n) {
					break-after: always;
				}
			}

			@media screen and (max-width: ($mobile)) {
				width: calc(100% - 1rem);

				&:nth-child(1n) {
					break-after: always;
				}
			}

			.info {
				align-self: flex-end;
				display: block;
				opacity: 0;
				width: 100%;
				padding: .25rem 0;
				text-align: center;
				background: rgba(0, 0, 0, 0.5);
				font-size: .75rem;
				font-weight: bold;
				color: var(--white);
				transition: opacity $transition;
				position: absolute;
			}

			img {
				object-fit: cover;
			}

			&:hover .info {
				opacity: 1;
			}
		}
	}

	.is-load-more-button {
		margin: 1rem auto 0 !important;
		display: block;
		width: 200px;
	}
}
</style>