<template>
	<modal title="Edit Station" class="edit-station-modal">
		<template v-slot:body>
			<div class="section left-section">
				<div class="col col-2">
					<div>
						<label class="label">Name</label>
						<p class="control">
							<input
								class="input"
								type="text"
								v-model="editing.name"
							/>
						</p>
					</div>
					<div>
						<label class="label">Display name</label>
						<p class="control">
							<input
								class="input"
								type="text"
								v-model="editing.displayName"
							/>
						</p>
					</div>
				</div>
				<div class="col col-1">
					<div>
						<label class="label">Description</label>
						<p class="control">
							<input
								class="input"
								type="text"
								v-model="editing.description"
							/>
						</p>
					</div>
				</div>
				<div class="col col-2" v-if="editing.genres">
					<div>
						<label class="label">Genre(s)</label>
						<p class="control has-addons">
							<input
								class="input"
								type="text"
								id="new-genre"
								v-model="genreInputValue"
								v-on:blur="blurGenreInput()"
								v-on:focus="focusGenreInput()"
								v-on:keydown="keydownGenreInput()"
								v-on:keyup.enter="addTag('genres')"
							/>
							<button
								class="button is-info add-button blue"
								v-on:click="addTag('genres')"
							>
								<i class="material-icons">add</i>
							</button>
						</p>
						<div
							class="autosuggest-container"
							v-if="
								(genreInputFocussed ||
									genreAutosuggestContainerFocussed) &&
									genreAutosuggestItems.length > 0
							"
							@mouseover="focusGenreContainer()"
							@mouseleave="blurGenreContainer()"
						>
							<span
								class="autosuggest-item"
								tabindex="0"
								v-on:click="selectGenreAutosuggest(item)"
								v-for="(item, index) in genreAutosuggestItems"
								:key="index"
								>{{ item }}</span
							>
						</div>
						<div class="list-container">
							<div
								class="list-item"
								v-for="(genre, index) in editing.genres"
								:key="index"
							>
								<div
									class="list-item-circle blue"
									v-on:click="removeTag('genres', index)"
								>
									<i class="material-icons">close</i>
								</div>
								<p>{{ genre }}</p>
							</div>
						</div>
					</div>
					<div>
						<label class="label">Blacklist genre(s)</label>
						<p class="control has-addons">
							<input
								class="input"
								type="text"
								v-model="blacklistGenreInputValue"
								v-on:blur="blurBlacklistGenreInput()"
								v-on:focus="focusBlacklistGenreInput()"
								v-on:keydown="keydownBlacklistGenreInput()"
								v-on:keyup.enter="addTag('blacklist-genres')"
							/>
							<button
								class="button is-info add-button red"
								v-on:click="addTag('blacklist-genres')"
							>
								<i class="material-icons">add</i>
							</button>
						</p>
						<div
							class="autosuggest-container"
							v-if="
								(blacklistGenreInputFocussed ||
									blacklistGenreAutosuggestContainerFocussed) &&
									blacklistGenreAutosuggestItems.length > 0
							"
							@mouseover="focusBlacklistGenreContainer()"
							@mouseleave="blurBlacklistGenreContainer()"
						>
							<span
								class="autosuggest-item"
								tabindex="0"
								v-on:click="
									selectBlacklistGenreAutosuggest(item)
								"
								v-for="(item,
								index) in blacklistGenreAutosuggestItems"
								:key="index"
								>{{ item }}</span
							>
						</div>
						<div class="list-container">
							<div
								class="list-item"
								v-for="(genre,
								index) in editing.blacklistedGenres"
								:key="index"
							>
								<div
									class="list-item-circle red"
									v-on:click="
										removeTag('blacklist-genres', index)
									"
								>
									<i class="material-icons">close</i>
								</div>
								<p>{{ genre }}</p>
							</div>
						</div>
					</div>
				</div>
			</div>
			<div class="section right-section">
				<div>
					<label class="label">Privacy</label>
					<div
						@mouseenter="privacyDropdownActive = true"
						@mouseleave="privacyDropdownActive = false"
						class="button-wrapper"
					>
						<button
							v-bind:class="{
								green: true,
								current: editing.privacy === 'public'
							}"
							v-if="
								privacyDropdownActive ||
									editing.privacy === 'public'
							"
							@click="updatePrivacyLocal('public')"
						>
							<i class="material-icons">public</i>
							Public
						</button>
						<button
							v-bind:class="{
								orange: true,
								current: editing.privacy === 'unlisted'
							}"
							v-if="
								privacyDropdownActive ||
									editing.privacy === 'unlisted'
							"
							@click="updatePrivacyLocal('unlisted')"
						>
							<i class="material-icons">link</i>
							Unlisted
						</button>
						<button
							v-bind:class="{
								red: true,
								current: editing.privacy === 'private'
							}"
							v-if="
								privacyDropdownActive ||
									editing.privacy === 'private'
							"
							@click="updatePrivacyLocal('private')"
						>
							<i class="material-icons">lock</i>
							Private
						</button>
					</div>
				</div>
				<div v-if="editing.type === 'community'">
					<label class="label">Mode</label>
					<div
						@mouseenter="modeDropdownActive = true"
						@mouseleave="modeDropdownActive = false"
						class="button-wrapper"
					>
						<button
							v-bind:class="{
								blue: true,
								current: editing.partyMode === false
							}"
							v-if="modeDropdownActive || !editing.partyMode"
							@click="updatePartyModeLocal(false)"
						>
							<i class="material-icons">playlist_play</i>
							Playlist
						</button>
						<button
							v-bind:class="{
								yellow: true,
								current: editing.partyMode === true
							}"
							v-if="
								modeDropdownActive || editing.partyMode === true
							"
							@click="updatePartyModeLocal(true)"
						>
							<i class="material-icons">emoji_people</i>
							Party
						</button>
					</div>
				</div>
				<div
					v-if="
						editing.type === 'community' &&
							editing.partyMode === true
					"
				>
					<label class="label">Queue lock</label>
					<div
						@mouseenter="queueLockDropdownActive = true"
						@mouseleave="queueLockDropdownActive = false"
						class="button-wrapper"
					>
						<button
							v-bind:class="{
								green: true,
								current: editing.locked
							}"
							v-if="queueLockDropdownActive || editing.locked"
							@click="updateQueueLockLocal(true)"
						>
							<i class="material-icons">lock</i>
							On
						</button>
						<button
							v-bind:class="{
								red: true,
								current: !editing.locked
							}"
							v-if="queueLockDropdownActive || !editing.locked"
							@click="updateQueueLockLocal(false)"
						>
							<i class="material-icons">lock_open</i>
							Off
						</button>
					</div>
				</div>
			</div>
		</template>
		<template v-slot:footer>
			<button class="button is-success" v-on:click="update()">
				Update Settings
			</button>
			<button
				v-if="station.type === 'community'"
				class="button is-danger"
				@click="deleteStation()"
			>
				Delete station
			</button>
		</template>
	</modal>
</template>

<script>
import { mapState, mapActions } from "vuex";

import Toast from "toasters";
import Modal from "./Modal.vue";
import io from "../../io";
import validation from "../../validation";

export default {
	computed: mapState({
		editing(state) {
			return this.$props.store.split("/").reduce((a, v) => a[v], state)
				.editing;
		},
		station(state) {
			return this.$props.store.split("/").reduce((a, v) => a[v], state)
				.station;
		}
	}),
	mounted() {
		io.getSocket(socket => {
			this.socket = socket;
			return socket;
		});
	},
	data() {
		return {
			genreInputValue: "",
			genreInputFocussed: false,
			genreAutosuggestContainerFocussed: false,
			keydownGenreInputTimeout: 0,
			genreAutosuggestItems: [],
			blacklistGenreInputValue: "",
			blacklistGenreInputFocussed: false,
			blacklistGenreAutosuggestContainerFocussed: false,
			blacklistKeydownGenreInputTimeout: 0,
			blacklistGenreAutosuggestItems: [],
			privacyDropdownActive: false,
			modeDropdownActive: false,
			queueLockDropdownActive: false,
			genres: [
				"Blues",
				"Country",
				"Disco",
				"Funk",
				"Hip-Hop",
				"Jazz",
				"Metal",
				"Oldies",
				"Other",
				"Pop",
				"Rap",
				"Reggae",
				"Rock",
				"Techno",
				"Trance",
				"Classical",
				"Instrumental",
				"House",
				"Electronic",
				"Christian Rap",
				"Lo-Fi",
				"Musical",
				"Rock 'n' Roll",
				"Opera",
				"Drum & Bass",
				"Club-House",
				"Indie",
				"Heavy Metal",
				"Christian rock",
				"Dubstep"
			]
		};
	},
	props: ["store"],
	methods: {
		update() {
			if (this.station.name !== this.editing.name) this.updateName();
			if (this.station.displayName !== this.editing.displayName)
				this.updateDisplayName();
			if (this.station.description !== this.editing.description)
				this.updateDescription();
			if (this.station.privacy !== this.editing.privacy)
				this.updatePrivacy();
			if (
				this.station.type === "community" &&
				this.station.partyMode !== this.editing.partyMode
			)
				this.updatePartyMode();
			if (
				this.station.type === "community" &&
				this.editing.partyMode &&
				this.station.locked !== this.editing.locked
			)
				this.updateQueueLock();
			if (this.$props.store !== "station") {
				if (
					this.station.genres.toString() !==
					this.editing.genres.toString()
				)
					this.updateGenres();
				if (
					this.station.blacklistedGenres.toString() !==
					this.editing.blacklistedGenres.toString()
				)
					this.updateBlacklistedGenres();
			}
		},
		updateName() {
			const { name } = this.editing;
			if (!validation.isLength(name, 2, 16))
				return new Toast({
					content: "Name must have between 2 and 16 characters.",
					timeout: 8000
				});
			if (!validation.regex.az09_.test(name))
				return new Toast({
					content:
						"Invalid name format. Allowed characters: a-z, 0-9 and _.",
					timeout: 8000
				});

			return this.socket.emit(
				"stations.updateName",
				this.editing._id,
				name,
				res => {
					if (res.status === "success") {
						if (this.station) this.station.name = name;
						else {
							this.$parent.stations.forEach((station, index) => {
								if (station._id === this.editing._id) {
									this.$parent.stations[index].name = name;
									return name;
								}

								return false;
							});
						}
					}

					new Toast({ content: res.message, timeout: 8000 });
				}
			);
		},
		updateDisplayName() {
			const { displayName } = this.editing;
			if (!validation.isLength(displayName, 2, 32))
				return new Toast({
					content:
						"Display name must have between 2 and 32 characters.",
					timeout: 8000
				});
			if (!validation.regex.ascii.test(displayName))
				return new Toast({
					content:
						"Invalid display name format. Only ASCII characters are allowed.",
					timeout: 8000
				});

			return this.socket.emit(
				"stations.updateDisplayName",
				this.editing._id,
				displayName,
				res => {
					if (res.status === "success") {
						if (this.station)
							this.station.displayName = displayName;
						else {
							this.$parent.stations.forEach((station, index) => {
								if (station._id === this.editing._id) {
									this.$parent.stations[
										index
									].displayName = displayName;
									return displayName;
								}

								return false;
							});
						}
					}

					new Toast({ content: res.message, timeout: 8000 });
				}
			);
		},
		updateDescription() {
			const { description } = this.editing;
			if (!validation.isLength(description, 2, 200))
				return new Toast({
					content:
						"Description must have between 2 and 200 characters.",
					timeout: 8000
				});

			let characters = description.split("");
			characters = characters.filter(character => {
				return character.charCodeAt(0) === 21328;
			});
			if (characters.length !== 0)
				return new Toast({
					content: "Invalid description format.",
					timeout: 8000
				});

			return this.socket.emit(
				"stations.updateDescription",
				this.editing._id,
				description,
				res => {
					if (res.status === "success") {
						if (this.station)
							this.station.description = description;
						else {
							this.$parent.stations.forEach((station, index) => {
								if (station._id === this.editing._id) {
									this.$parent.stations[
										index
									].description = description;
									return description;
								}

								return false;
							});
						}

						return new Toast({
							content: res.message,
							timeout: 4000
						});
					}

					return new Toast({ content: res.message, timeout: 8000 });
				}
			);
		},
		updatePrivacyLocal(privacy) {
			if (this.editing.privacy === privacy) return;
			this.editing.privacy = privacy;
			this.privacyDropdownActive = false;
		},
		updatePrivacy() {
			this.socket.emit(
				"stations.updatePrivacy",
				this.editing._id,
				this.editing.privacy,
				res => {
					if (res.status === "success") {
						if (this.station)
							this.station.privacy = this.editing.privacy;
						else {
							this.$parent.stations.forEach((station, index) => {
								if (station._id === this.editing._id) {
									this.$parent.stations[
										index
									].privacy = this.editing.privacy;
									return this.editing.privacy;
								}

								return false;
							});
						}
						return new Toast({
							content: res.message,
							timeout: 4000
						});
					}

					return new Toast({ content: res.message, timeout: 8000 });
				}
			);
		},
		updateGenres() {
			this.socket.emit(
				"stations.updateGenres",
				this.editing._id,
				this.editing.genres,
				res => {
					if (res.status === "success") {
						const genres = JSON.parse(
							JSON.stringify(this.editing.genres)
						);
						if (this.station) this.station.genres = genres;
						this.$parent.stations.forEach((station, index) => {
							if (station._id === this.editing._id) {
								this.$parent.stations[index].genres = genres;
								return genres;
							}

							return false;
						});

						return new Toast({
							content: res.message,
							timeout: 4000
						});
					}

					return new Toast({ content: res.message, timeout: 8000 });
				}
			);
		},
		updateBlacklistedGenres() {
			this.socket.emit(
				"stations.updateBlacklistedGenres",
				this.editing._id,
				this.editing.blacklistedGenres,
				res => {
					if (res.status === "success") {
						const blacklistedGenres = JSON.parse(
							JSON.stringify(this.editing.blacklistedGenres)
						);
						if (this.station)
							this.station.blacklistedGenres = blacklistedGenres;
						this.$parent.stations.forEach((station, index) => {
							if (station._id === this.editing._id) {
								this.$parent.stations[
									index
								].blacklistedGenres = blacklistedGenres;
								return blacklistedGenres;
							}

							return false;
						});
						return new Toast({
							content: res.message,
							timeout: 4000
						});
					}

					return new Toast({ content: res.message, timeout: 8000 });
				}
			);
		},
		updatePartyModeLocal(partyMode) {
			if (this.editing.partyMode === partyMode) return;
			this.editing.partyMode = partyMode;
			this.modeDropdownActive = false;
		},
		updatePartyMode() {
			this.socket.emit(
				"stations.updatePartyMode",
				this.editing._id,
				this.editing.partyMode,
				res => {
					if (res.status === "success") {
						if (this.station)
							this.station.partyMode = this.editing.partyMode;
						// if (this.station)
						// 	this.station.partyMode = this.editing.partyMode;
						// this.$parent.stations.forEach((station, index) => {
						// 	if (station._id === this.editing._id) {
						// 		this.$parent.stations[
						// 			index
						// 		].partyMode = this.editing.partyMode;
						// 		return this.editing.partyMode;
						// 	}

						// 	return false;
						// });

						return new Toast({
							content: res.message,
							timeout: 4000
						});
					}

					return new Toast({ content: res.message, timeout: 8000 });
				}
			);
		},
		updateQueueLockLocal(locked) {
			if (this.editing.locked === locked) return;
			this.editing.locked = locked;
			this.queueLockDropdownActive = false;
		},
		updateQueueLock() {
			this.socket.emit("stations.toggleLock", this.editing._id, res => {
				console.log(res);
				if (res.status === "success") {
					if (this.station) this.station.locked = res.data;
					return new Toast({
						content: `Toggled queue lock succesfully to ${res.data}`,
						timeout: 4000
					});
				}
				return new Toast({
					content: "Failed to toggle queue lock.",
					timeout: 8000
				});
			});
		},
		deleteStation() {
			this.socket.emit("stations.remove", this.editing._id, res => {
				if (res.status === "success")
					this.closeModal({
						sector: "station",
						modal: "editStation"
					});
				return new Toast({ content: res.message, timeout: 8000 });
			});
		},
		blurGenreInput() {
			this.genreInputFocussed = false;
		},
		focusGenreInput() {
			this.genreInputFocussed = true;
		},
		keydownGenreInput() {
			clearTimeout(this.keydownGenreInputTimeout);
			this.keydownGenreInputTimeout = setTimeout(() => {
				if (this.genreInputValue.length > 1) {
					this.genreAutosuggestItems = this.genres.filter(genre => {
						return genre
							.toLowerCase()
							.startsWith(this.genreInputValue.toLowerCase());
					});
				} else this.genreAutosuggestItems = [];
			}, 1000);
		},
		focusGenreContainer() {
			this.genreAutosuggestContainerFocussed = true;
		},
		blurGenreContainer() {
			this.genreAutosuggestContainerFocussed = false;
		},
		selectGenreAutosuggest(value) {
			this.genreInputValue = value;
		},
		blurBlacklistGenreInput() {
			this.blacklistGenreInputFocussed = false;
		},
		focusBlacklistGenreInput() {
			this.blacklistGenreInputFocussed = true;
		},
		keydownBlacklistGenreInput() {
			clearTimeout(this.keydownBlacklistGenreInputTimeout);
			this.keydownBlacklistGenreInputTimeout = setTimeout(() => {
				if (this.blacklistGenreInputValue.length > 1) {
					this.blacklistGenreAutosuggestItems = this.genres.filter(
						genre => {
							return genre
								.toLowerCase()
								.startsWith(
									this.blacklistGenreInputValue.toLowerCase()
								);
						}
					);
				} else this.blacklistGenreAutosuggestItems = [];
			}, 1000);
		},
		focusBlacklistGenreContainer() {
			this.blacklistGenreAutosuggestContainerFocussed = true;
		},
		blurBlacklistGenreContainer() {
			this.blacklistGenreAutosuggestContainerFocussed = false;
		},
		selectBlacklistGenreAutosuggest(value) {
			this.blacklistGenreInputValue = value;
		},
		addTag(type) {
			if (type === "genres") {
				const genre = this.genreInputValue.toLowerCase().trim();
				if (this.editing.genres.indexOf(genre) !== -1)
					return new Toast({
						content: "Genre already exists",
						timeout: 3000
					});
				if (genre) {
					this.editing.genres.push(genre);
					this.genreInputValue = "";
					return false;
				}

				return new Toast({
					content: "Genre cannot be empty",
					timeout: 3000
				});
			}
			if (type === "blacklist-genres") {
				const genre = this.blacklistGenreInputValue
					.toLowerCase()
					.trim();
				if (this.editing.blacklistedGenres.indexOf(genre) !== -1)
					return new Toast({
						content: "Blacklist genre already exists",
						timeout: 3000
					});
				if (genre) {
					this.editing.blacklistedGenres.push(genre);
					this.blacklistGenreInputValue = "";
					return false;
				}

				return new Toast({
					content: "Blacklist genre cannot be empty",
					timeout: 3000
				});
			}

			return false;
		},
		removeTag(type, index) {
			if (type === "genres") this.editing.genres.splice(index, 1);
			else if (type === "blacklist-genres")
				this.editing.blacklistedGenres.splice(index, 1);
		},
		...mapActions("modals", ["closeModal"])
	},
	components: { Modal }
};
</script>

<style lang="scss">
@import "styles/global.scss";

.night-mode {
	.modal-card,
	.modal-card-head,
	.modal-card-body,
	.modal-card-foot {
		background-color: $night-mode-secondary;
	}

	.section {
		background-color: #111 !important;
		border: 0 !important;
	}

	.label,
	p,
	strong {
		color: #ddd;
	}
}

.edit-station-modal {
	.modal-card-title {
		text-align: center;
		margin-left: 24px;
	}

	.modal-card {
		width: 800px;
		height: 550px;

		.modal-card-body {
			padding: 16px;
			display: flex;
		}
	}
}
</style>

<style lang="scss" scoped>
@import "styles/global.scss";

.section {
	border: 1px solid #a3e0ff;
	background-color: #f4f4f4;
	border-radius: 5px;
	padding: 16px;
}

.left-section {
	width: 595px;
	display: grid;
	gap: 16px;
	grid-template-rows: min-content min-content auto;

	.control {
		input {
			width: 100%;
		}

		.add-button {
			width: 32px;

			&.blue {
				background-color: $musareBlue !important;
			}

			&.red {
				background-color: $red !important;
			}

			i {
				font-size: 32px;
			}
		}
	}

	.col {
		> div {
			position: relative;
		}
	}

	.list-item-circle {
		width: 16px;
		height: 16px;
		border-radius: 8px;
		cursor: pointer;
		margin-right: 8px;
		float: left;
		-webkit-touch-callout: none;
		-webkit-user-select: none;
		-khtml-user-select: none;
		-moz-user-select: none;
		-ms-user-select: none;
		user-select: none;

		&.blue {
			background-color: $musareBlue;

			i {
				color: $musareBlue;
			}
		}

		&.red {
			background-color: $red;

			i {
				color: $red;
			}
		}

		i {
			font-size: 14px;
			margin-left: 1px;
		}
	}

	.list-item-circle:hover,
	.list-item-circle:focus {
		i {
			color: white;
		}
	}

	.list-item > p {
		line-height: 16px;
		word-wrap: break-word;
		width: calc(100% - 24px);
		left: 24px;
		float: left;
		margin-bottom: 8px;
	}

	.list-item:last-child > p {
		margin-bottom: 0;
	}

	.autosuggest-container {
		position: absolute;
		background: white;
		width: calc(100% + 1px);
		top: 57px;
		z-index: 200;
		overflow: auto;
		max-height: 100%;
		clear: both;

		.autosuggest-item {
			padding: 8px;
			display: block;
			border: 1px solid #dbdbdb;
			margin-top: -1px;
			line-height: 16px;
			cursor: pointer;
			-webkit-user-select: none;
			-ms-user-select: none;
			-moz-user-select: none;
			user-select: none;
		}

		.autosuggest-item:hover,
		.autosuggest-item:focus {
			background-color: #eee;
		}

		.autosuggest-item:first-child {
			border-top: none;
		}

		.autosuggest-item:last-child {
			border-radius: 0 0 3px 3px;
		}
	}
}

.right-section {
	width: 157px;
	margin-left: 16px;
	display: grid;
	gap: 16px;
	grid-template-rows: min-content min-content min-content;

	.button-wrapper {
		display: flex;
		flex-direction: column;
	}

	button {
		width: 100%;
		height: 36px;
		border: 0;
		border-radius: 10px;
		font-size: 18px;
		color: white;
		box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25);
		display: block;
		text-align: center;
		justify-content: center;
		display: inline-flex;
		-ms-flex-align: center;
		align-items: center;
		-moz-user-select: none;
		user-select: none;
		cursor: pointer;
		margin-bottom: 16px;
		padding: 0;

		&.current {
			order: -1;
		}

		&.red {
			background-color: $red;
		}

		&.green {
			background-color: $green;
		}

		&.blue {
			background-color: $musareBlue;
		}

		&.orange {
			background-color: $light-orange;
		}

		&.yellow {
			background-color: $yellow;
		}

		i {
			font-size: 20px;
			margin-right: 4px;
		}
	}
}

.col {
	display: grid;
	grid-column-gap: 16px;
}

.col-1 {
	grid-template-columns: auto;
}

.col-2 {
	grid-template-columns: auto auto;
}
</style>