<template>
	<div
		:class="{ 'is-loading': passwordUpdateService.loading || emailUpdateService.loading || totpService.loading }"
		class="loader-container is-max-width-desktop">
		<!-- Password update -->
		<card title="Update Your Password">
			<form @submit.prevent="updatePassword()">
				<div class="field">
					<label class="label" for="newPassword">New Password</label>
					<div class="control">
						<input
							@keyup.enter="updatePassword"
							class="input"
							id="newPassword"
							placeholder="The new password..."
							type="password"
							v-model="passwordUpdate.newPassword"/>
					</div>
				</div>
				<div class="field">
					<label class="label" for="newPasswordConfirm">New Password Confirmation</label>
					<div class="control">
						<input
							@keyup.enter="updatePassword"
							class="input"
							id="newPasswordConfirm"
							placeholder="Confirm your new password..."
							type="password"
							v-model="passwordConfirm"/>
					</div>
				</div>
				<div class="field">
					<label class="label" for="currentPassword">Current Password</label>
					<div class="control">
						<input
							@keyup.enter="updatePassword"
							class="input"
							id="currentPassword"
							placeholder="Your current password"
							type="password"
							v-model="passwordUpdate.oldPassword"/>
					</div>
				</div>
			</form>

			<x-button
				:loading="passwordUpdateService.loading"
				@click="updatePassword()"
				class="is-fullwidth mt-4">
				Save
			</x-button>
		</card>

		<!-- Update E-Mail -->
		<card title="Update Your E-Mail Address">
			<form @submit.prevent="updateEmail()">
				<div class="field">
					<label class="label" for="newEmail">New Email Address</label>
					<div class="control">
						<input
							@keyup.enter="updateEmail"
							class="input"
							id="newEmail"
							placeholder="The new email address..."
							type="email"
							v-model="emailUpdate.newEmail"/>
					</div>
				</div>
				<div class="field">
					<label class="label" for="currentPassword">Current Password</label>
					<div class="control">
						<input
							@keyup.enter="updateEmail"
							class="input"
							id="currentPassword"
							placeholder="Your current password"
							type="password"
							v-model="emailUpdate.password"/>
					</div>
				</div>
			</form>

			<x-button
				:loading="emailUpdateService.loading"
				@click="updateEmail()"
				class="is-fullwidth mt-4">
				Save
			</x-button>
		</card>

		<!-- General -->
		<card title="General Settings" class="general-settings">
			<div class="field">
				<label class="label" for="newName">Name</label>
				<div class="control">
					<input
						@keyup.enter="updateSettings"
						class="input"
						id="newName"
						placeholder="The new name"
						type="text"
						v-model="settings.name"/>
				</div>
			</div>
			<div class="field">
				<label class="checkbox">
					<input type="checkbox" v-model="settings.emailRemindersEnabled"/>
					Send me Reminders for tasks via Email
				</label>
			</div>
			<div class="field">
				<label class="checkbox">
					<input type="checkbox" v-model="playSoundWhenDone"/>
					Play a sound when marking tasks as done
				</label>
			</div>

			<x-button
				:loading="userSettingsService.loading"
				@click="updateSettings()"
				class="is-fullwidth mt-4"
			>
				Save
			</x-button>
		</card>

		<!-- Avatar -->
		<avatar-settings/>

		<!-- TOTP -->
		<card title="Two Factor Authentication" v-if="totpEnabled">
			<x-button
				:loading="totpService.loading"
				@click="totpEnroll()"
				v-if="!totpEnrolled && totp.secret === ''">
				Enroll
			</x-button>
			<template v-else-if="totp.secret !== '' && !totp.enabled">
				<p>
					To finish your setup, use this secret in your totp app (Google Authenticator or similar):
					<strong>{{ totp.secret }}</strong><br/>
					After that, enter a code from your app below.
				</p>
				<p>
					Alternatively you can scan this QR code:<br/>
					<img :src="totpQR" alt=""/>
				</p>
				<div class="field">
					<label class="label" for="totpConfirmPasscode">Passcode</label>
					<div class="control">
						<input
							@keyup.enter="totpConfirm()"
							class="input"
							id="totpConfirmPasscode"
							placeholder="A code generated by your totp application"
							type="text"
							v-model="totpConfirmPasscode"/>
					</div>
				</div>
				<x-button @click="totpConfirm()">Confirm</x-button>
			</template>
			<template v-else-if="totp.secret !== '' && totp.enabled">
				<p>
					You've sucessfully set up two factor authentication!
				</p>
				<p v-if="!totpDisableForm">
					<x-button @click="totpDisableForm = true" class="is-danger">Disable</x-button>
				</p>
				<div v-if="totpDisableForm">
					<div class="field">
						<label class="label" for="currentPassword">Please Enter Your Password</label>
						<div class="control">
							<input
								@keyup.enter="totpDisable"
								class="input"
								id="currentPassword"
								placeholder="Your current password"
								type="password"
								v-focus
								v-model="totpDisablePassword"/>
						</div>
					</div>
					<x-button @click="totpDisable()" class="is-danger">Disable two factor authentication</x-button>
				</div>
			</template>
		</card>

		<!-- Migration -->
		<card title="Migrate from other services to Vikunja" v-if="migratorsEnabled">
			<x-button
				:to="{name: 'migrate.start'}"
			>
				Import your data into Vikunja
			</x-button>
		</card>

		<!-- Caldav -->
		<card v-if="caldavEnabled" title="Caldav">
			<p>
				You can connect Vikunja to caldav clients to view and manage all tasks from different clients.
				Enter this url into your client:
			</p>
			<div class="field has-addons no-input-mobile">
				<div class="control is-expanded">
					<input type="text" v-model="caldavUrl" class="input" readonly/>
				</div>
				<div class="control">
					<x-button
						@click="copy(caldavUrl)"
						:shadow="false"
						v-tooltip="'Copy to clipboard'"
						icon="paste"
					/>
				</div>
			</div>
			<p>
				<a href="https://vikunja.io/docs/caldav/" target="_blank">
					More information about caldav in Vikunja
				</a>
			</p>
		</card>
	</div>
</template>

<script>
import PasswordUpdateModel from '../../models/passwordUpdate'
import PasswordUpdateService from '../../services/passwordUpdateService'
import EmailUpdateService from '../../services/emailUpdate'
import EmailUpdateModel from '../../models/emailUpdate'
import TotpModel from '../../models/totp'
import TotpService from '../../services/totp'
import UserSettingsService from '../../services/userSettings'
import UserSettingsModel from '../../models/userSettings'
import {playSoundWhenDoneKey} from '@/helpers/playPop'

import {mapState} from 'vuex'

import AvatarSettings from '../../components/user/avatar-settings'
import copy from 'copy-to-clipboard'

export default {
	name: 'Settings',
	data() {
		return {
			passwordUpdateService: PasswordUpdateService,
			passwordUpdate: PasswordUpdateModel,
			passwordConfirm: '',

			emailUpdateService: EmailUpdateService,
			emailUpdate: EmailUpdateModel,

			totpService: TotpService,
			totp: TotpModel,
			totpQR: '',
			totpEnrolled: false,
			totpConfirmPasscode: '',
			totpDisableForm: false,
			totpDisablePassword: '',
			playSoundWhenDone: false,

			settings: UserSettingsModel,
			userSettingsService: UserSettingsService,
		}
	},
	components: {
		AvatarSettings,
	},
	created() {
		this.passwordUpdateService = new PasswordUpdateService()
		this.passwordUpdate = new PasswordUpdateModel()

		this.emailUpdateService = new EmailUpdateService()
		this.emailUpdate = new EmailUpdateModel()

		this.totpService = new TotpService()
		this.totp = new TotpModel()

		this.userSettingsService = new UserSettingsService()
		this.settings = new UserSettingsModel({
			name: this.$store.state.auth.info.name,
			emailRemindersEnabled: this.$store.state.auth.info.emailRemindersEnabled ?? false,
		})

		this.playSoundWhenDone = localStorage.getItem(playSoundWhenDoneKey) === 'true' || localStorage.getItem(playSoundWhenDoneKey) === null

		this.totpStatus()
	},
	mounted() {
		this.setTitle('Settings')
	},
	computed: {
		caldavUrl() {
			let apiBase = window.API_URL.replace('/api/v1', '')
			if (apiBase === '') { // Frontend and api on the same host which means we need to prefix the frontend url
				apiBase = this.$store.state.config.frontendUrl
			}
			if (apiBase.endsWith('/')) {
				apiBase = apiBase.substr(0, apiBase.length - 1)
			}

			return `${apiBase}/dav/principals/${this.userInfo.username}/`
		},
		...mapState({
			totpEnabled: state => state.config.totpEnabled,
			migratorsEnabled: state => state.config.availableMigrators !== null && state.config.availableMigrators.length > 0,
			caldavEnabled: state => state.config.caldavEnabled,
			userInfo: state => state.auth.info,
		})
	},
	methods: {
		updatePassword() {
			if (this.passwordConfirm !== this.passwordUpdate.newPassword) {
				this.error({message: 'The new password and its confirmation don\'t match.'}, this)
				return
			}

			this.passwordUpdateService.update(this.passwordUpdate)
				.then(() => {
					this.success({message: 'The password was successfully updated.'}, this)
				})
				.catch(e => this.error(e, this))
		},
		updateEmail() {
			this.emailUpdateService.update(this.emailUpdate)
				.then(() => {
					this.success({message: 'Your email address was successfully updated. We\'ve sent you a link to confirm it.'}, this)
				})
				.catch(e => this.error(e, this))
		},
		totpStatus() {
			if (!this.totpEnabled) {
				return
			}
			this.totpService.get()
				.then(r => {
					this.$set(this, 'totp', r)
					this.totpSetQrCode()
				})
				.catch(e => {
					// Error code 1016 means totp is not enabled, we don't need an error in that case.
					if (e.response && e.response.data && e.response.data.code && e.response.data.code === 1016) {
						this.totpEnrolled = false
						return
					}

					this.error(e, this)
				})
		},
		totpSetQrCode() {
			this.totpService.qrcode()
				.then(qr => {
					const urlCreator = window.URL || window.webkitURL
					this.totpQR = urlCreator.createObjectURL(qr)
				})
		},
		totpEnroll() {
			this.totpService.enroll()
				.then(r => {
					this.totpEnrolled = true
					this.$set(this, 'totp', r)
					this.totpSetQrCode()
				})
				.catch(e => this.error(e, this))
		},
		totpConfirm() {
			this.totpService.enable({passcode: this.totpConfirmPasscode})
				.then(() => {
					this.$set(this.totp, 'enabled', true)
					this.success({message: 'You\'ve successfully confirmed your totp setup and can use it from now on!'}, this)
				})
				.catch(e => this.error(e, this))
		},
		totpDisable() {
			this.totpService.disable({password: this.totpDisablePassword})
				.then(() => {
					this.totpEnrolled = false
					this.$set(this, 'totp', new TotpModel())
					this.success({message: 'Two factor authentication was sucessfully disabled.'}, this)
				})
				.catch(e => this.error(e, this))
		},
		updateSettings() {
			localStorage.setItem(playSoundWhenDoneKey, this.playSoundWhenDone)

			this.userSettingsService.update(this.settings)
				.then(() => {
					this.$store.commit('auth/setUserSettings', this.settings)
					this.success({message: 'The name was successfully changed.'}, this)
				})
				.catch(e => this.error(e, this))
		},
		copy(text) {
			copy(text)
		},
	},
}
</script>
