<template>
	<w-dialog
		:value="isVisible"
		dialog-class="task-viewer-dialog"
		class="task-viewer-overlay"
		transition=""
		width="850"
		:style="viewerStyle"
		@close="setTaskHidden"
	>
		<section class="task-viewer" @keydown.esc="saveTask">
			<aside
				class="task-viewer__toolbar"
				:class="computeToolbarClass"
				@mouseover="toolbarExpanded = true"
				@mouseleave="toolbarExpanded = false"
			>
				<div class="task-viewer__toolbar-contents">
					<div v-if="!isLoading" class="task-viewer__toolbar-container">
						
						<!-- ANCHOR Close -->
						<div
							class="task-viewer__toolbar-item"
							title="Close task"
							role="button"
							@click="setTaskHidden"
						>
							<w-icon>
								mdi mdi-close
							</w-icon>
							Dismiss
						</div>

						<w-divider />

						<!-- ANCHOR Join or leave task -->
						<template v-if="$store.state.profile">
							<div
								v-if="!isCurrentlyAssigned"
								class="task-viewer__toolbar-item"
								title="Join task"
								role="button"
								@click="addTaskAssignee($store.state.profile)"
							>
								<w-icon>
									mdi mdi-account-plus
								</w-icon>
								Join task
							</div>
							<div
								v-else
								class="task-viewer__toolbar-item"
								title="Leave task"
								role="button"
								@click="removeTaskAssignee($store.state.profile)"
							>
								<w-icon>
									mdi mdi-account-minus
								</w-icon>
								Leave task
							</div>
						</template>

						<!-- ANCHOR Upload attachment -->
						<div
							class="task-viewer__toolbar-item"
							title="Attach file"
							role="button"
							@click="requestFileUpload"
						>
							<w-icon rotate45a>
								mdi mdi-attachment
							</w-icon>
							Attach file
						</div>

						<!-- TODO This should be moved, it is not an action -->
						<!-- ANCHOR Checklist -->
						<!-- <div
							class="task-viewer__toolbar-item"
							title="Checklist"
						>
							<w-icon>
								mdi mdi-checkbox-marked-circle-outline
							</w-icon>
							Checklist
						</div> -->

						<!-- ANCHOR Pinned -->
						<div
							v-if="!task.isPinned"
							class="task-viewer__toolbar-item"
							title="Pin task"
							role="button"
							@click="toggleTaskPinned"
						>
							<w-icon>
								mdi mdi-pin
							</w-icon>
							Pin task
						</div>
						<div
							v-else
							class="task-viewer__toolbar-item"
							title="Unpin task"
							role="button"
							@click="toggleTaskPinned"
						>
							<w-icon>
								mdi mdi-pin-off
							</w-icon>
							Unpin task
						</div>

						<!-- ANCHOR Move -->
						<div
							class="task-viewer__toolbar-item"
							title="Move task"
							role="button"
						>
							<w-icon>
								mdi mdi-arrow-right-bottom-bold
							</w-icon>
							Move task
						</div>

						<!-- ANCHOR Duplicate -->
						<div
							class="task-viewer__toolbar-item"
							title="Copy task"
							role="button"
						>
							<w-icon>
								mdi mdi-content-duplicate
							</w-icon>
							Copy task
						</div>

						<!-- ANCHOR Watch -->
						<div
							class="task-viewer__toolbar-item"
							title="Watch"
							role="button"
						>
							<w-icon>
								mdi mdi-eye
							</w-icon>
							Watch
						</div>

						<!-- ANCHOR Share -->
						<div
							class="task-viewer__toolbar-item"
							title="Share"
							role="button"
						>
							<w-icon>
								mdi mdi-share-variant
							</w-icon>
							Share
						</div>

						<!-- ANCHOR Delete -->
						<div
							class="task-viewer__toolbar-item"
							title="Archive"
							role="button"
							@click="removeTask"
						>
							<w-icon>
								mdi mdi-delete
							</w-icon>
							Archive
						</div>

						<VindiSpacer />

						<div
							class="task-viewer__toolbar-item"
							role="button"
							@click="toggletoolbarExpansion"
						>
							<w-icon>
								mdi mdi-chevron-right
							</w-icon>
							<div>
								<div>
									Collapse toolbar
								</div>
								<small>
									Disable auto reveal
								</small>
							</div>
						</div>
					</div>
				</div>
			</aside>
			<div class="task-viewer__content">
				<div v-if="isLoading" class="task-viewer__loading">
					<w-progress
						color="primary"
						circle
					/>
				</div>
				<template v-else>
				
					<!-- ANCHOR Parent task -->
					<div
						v-if="task.parentTask"
						class="task-viewer__parent"
						@click="$store.dispatch('openTaskViewer', task.parentTask.id);"
					>
						<w-icon>
							mdi mdi-subdirectory-arrow-right
						</w-icon>
						Child task of
						<span class="task-viewer__parent-summary">
							#{{ task.parentTask.localId }}
							{{ task.parentTask.summary }}
						</span>
					</div>

					<!-- ANCHOR Local id and summary -->
					<div class="task-viewer__row">
						<span class="task-viewer__id">
							#{{ task.localId }}
						</span>
						<w-input
							ref="summary"
							v-model="summary"
							class="task-viewer__summary"
							bg-color="transparent"
							@keydown.enter="$event.target.blur()"
							@blur="updateSummary"
						/>
					</div>

					<w-divider />

					<!-- ANCHOR Author and current list -->
					<section class="task-viewer__row">
						<w-flex :gap="3">
							<VindiAvatar
								:size="30"
								:profile="task.creator"
								@click.native="setTaskHidden"
							/>
							<div>
								<div class="task-viewer__created-by">
									Created by {{ task.creator.fullName }}
								</div>
								<div class="task-viewer__created-at">
									{{ creationTime }}
								</div>
							</div>
						</w-flex>
						<VindiSpacer />
						<w-icon class="task-viewer__task-list-icon">
							mdi mdi-format-list-bulleted
						</w-icon>
						<w-select
							v-model="taskList"
							class="task-viewer__task-list"
							:items="taskListItems"
							:menu-props="{'z-index': 600}"
							bg-color="transparent"
							color="black"
							no-unselect
						/>
					</section>

					<!-- ANCHOR Description -->
					<section class="task-viewer__description">
						<template v-if="isEditingDesc">
							<VindiEditor
								ref="descEditor"
								v-model="description"
								placeholder="Add a description..."
								class="task-viewer__description-editor"
							/>
							<w-flex :gap="2">
								<VindiSpacer />
								<w-button
									bg-color="transparent"
									icon="mdi mdi-close"
									@click="discardDescription"
								/>
								<w-button
									@click="updateDescription"
								>
									Save
								</w-button>
							</w-flex>
						</template>
						<div
							v-else
							@click="editDescription"
						>
							<div
								v-if="description"
								class="task-viewer__description-preview markdown-enabled"
								v-html="renderedDescription"
							/>
							<div
								v-else
								class="task-viewer__description-placeholder"
							>
								Add a description...
							</div>
						</div>
					</section>

					<!-- ANCHOR Attachments -->
					<section
						v-if="task && attachments.length"
						class="task-viewer__section"
					>
						<div class="task-viewer__section-title">
							Attachments
						</div>
						<div class="task-viewer__attachments">
							<div
								v-for="attachment in attachments"
								:key="attachment.id"
								class="task-viewer__attachment"
							>
								<div
									class="task-viewer__attachment-preview"
									:style="computePreviewStyle(attachment)"
								>
									<w-icon size="50">
										mdi mdi-file-document
									</w-icon>
								</div>
								<div class="task-viewer__attachment-info">
									<div
										class="project-storage__name"
										:title="`Open ${attachment.name}`"
										@click="openAttachment(attachment)"
									>
										{{ attachment.name }}
									</div>
									<div class="task-viewer__attachment-uploader">
										Attached {{ attachDuration(attachment) }} by {{ formatUploader(attachment) }}
									</div>
									<div class="task-viewer__attachment-size">
										{{ formatAttachmentSize(attachment) }}
									</div>
								</div>
								<div class="task-viewer__attachment-options">
									<w-menu
										transition="slide-fade-down"
										hide-on-menu-click
										z-index="600"
										align-left
										custom
									>
										<template #activator="{ on }">
											<w-button
												icon="mdi mdi-chevron-down"
												text
												lg
												v-on="on"
											/>
										</template>
										<div class="simple-list">
											<p class="simple-list__title">
												Attachment
											</p>
											<w-divider />
											<div class="simple-list__list">
												<div 
													v-if="bannerImage != null && bannerImage.id == attachment.id"
													class="simple-list__item"
													@click="removeCover"
												>
													<w-icon>
														mdi mdi-image-area
													</w-icon>
													Remove cover
												</div>
												<div 
													v-else
													class="simple-list__item"
													@click="setCover(attachment)"
												>
													<w-icon>
														mdi mdi-image-area
													</w-icon>
													Make cover
												</div>
												<div
													class="simple-list__item"
													@click="copyAttachmentLink(attachment)"
												>
													<w-icon>
														mdi mdi-link
													</w-icon>
													Copy Link
												</div>
												<div
													class="simple-list__item"
													@click="downloadAttachment(attachment)"
												>
													<w-icon>
														mdi mdi-download
													</w-icon>
													Download
												</div>
												<div
													class="simple-list__item"
													@click="detachAttachment(attachment)"
												>
													<w-icon>
														mdi mdi-link-off
													</w-icon>
													Detach
												</div>
												<div
													class="simple-list__item"
													@click="deleteAttachment(attachment)"
												>
													<w-icon>
														mdi mdi-delete
													</w-icon>
													Delete
												</div>
											</div>
										</div>
									</w-menu>
								</div>
							</div>
						</div>
					</section>

					<!-- ANCHOR Checklists -->
					<section
						class="task-viewer__section"
					>
						<div class="task-viewer__section-title">
							Checklists
						</div>
						TODO
					</section>
				</template>
			</div>
			<aside class="task-viewer__panel">
				<template v-if="!isLoading">

					<!-- ANCHOR Labels -->
					<div class="task-viewer__panel-section task-viewer__labels">
						<div class="task-viewer__panel-title">
							Labels
							<VindiSpacer />
							<w-menu
								v-model="labelSelector"
								z-index="600"
								align-left
								custom
							>
								<template #activator="{ on }">
									<w-icon v-on="on">
										mdi mdi-cog
									</w-icon>
								</template>
								<div class="simple-list">
									<TaskLabelSelector
										:labels="labelIds"
										:project-id="task.project.id"
										@add="addTaskLabel"
										@remove="removeTaskLabel"
									/>
								</div>
							</w-menu>
						</div>
						<div
							v-if="!labelIds.length"
							class="task-viewer__no-items"
						>
							No labels assigned
						</div>
						<div
							v-for="label in task.labels"
							:key="label.id"
							@click="labelSelector = !labelSelector"
						>
							<TaskLabel
								:value="label"
								class="task-viewer__label"
							/>
						</div>
					</div>

					<!-- ANCHOR Assignees -->
					<div class="task-viewer__panel-section task-viewer__assignees">
						<div class="task-viewer__panel-title">
							Assignees
							<VindiSpacer />
							<w-menu
								z-index="600"
								align-left
								custom
							>
								<template #activator="{ on }">
									<w-icon v-on="on">
										mdi mdi-cog
									</w-icon>
								</template>
								<div class="simple-list">
									<TaskAssigneeSelector
										:assignees="assigneeIds"
										:project-id="task.project.id"
										@add="addTaskAssignee"
										@remove="removeTaskAssignee"
									/>
								</div>
							</w-menu>
						</div>
						<div
							v-if="!assigneeIds.length"
							class="task-viewer__no-items"
						>
							No members assigned
						</div>
						<div
							v-for="(user, i) in task.assignees"
							:key="i"
							class="task-viewer__assignee"
						>
							<VindiAvatar
								:profile="user"
								:size="20"
								:show-border="false"
								@click.native="setTaskHidden"
							/>
							{{ user.fullName }}
						</div>
					</div>

					<!-- ANCHOR Calendar -->
					<div class="task-viewer__panel-section task-viewer__calendar">
						<div class="task-viewer__panel-title">
							Calendar
							<VindiSpacer />
							<w-menu
								z-index="600"
								menu-class="task-viewer__calendar-menu"
								align-left
								custom
							>
								<template #activator="{ on }">
									<w-icon v-on="on">
										mdi mdi-cog
									</w-icon>
								</template>
								<div class="simple-list">
									<w-accordion
										v-model="calendarOption"
										:items="calendarOptions"
										expand-single
									>	
										<template #item-title="{ item }">
											<div>
												<strong>
													{{ item.title }}
												</strong>
												<div class="task-viewer__calendar-value">
													{{ getCalendarValue(item.field) ? formatCalendarTimer(item.field) : 'None' }}
												</div>
											</div>
											<VindiSpacer />
											<w-button
												v-if="getCalendarValue(item.field)"
												icon="mdi mdi-close"
												text
												@click.stop="clearCalendarValue(item.field)"
											/>
										</template>
										<template #item-content="{ item }">
											<VindiDatePicker
												:value="getCalendarValue(item.field)"
												show-time
												@input="updateCalendarValue($event, item.field)"
											/>
										</template>
									</w-accordion>
								</div>
							</w-menu>
						</div>
						<div
							v-if="!task.startTime && !task.endTime"
							class="task-viewer__no-items"
						>
							No dates specified
						</div>
						<div
							v-if="task.startTime || task.endTime"
							class="task-viewer__calendar-card"
						>
							<div v-if="task.startTime">
								<div class="task-viewer__calendar-title">
									Start Date
								</div>
								{{ formatDate(task.startTime) }}
								<div
									v-if="isTimeDefined(task.startTime)"
									class="task-viewer__calendar-time"
								>
									{{ formatTime(task.startTime) }}
								</div>
							</div>
							<div v-if="task.endTime">
								<div class="task-viewer__calendar-title">
									Due Date
								</div>
								{{ formatDate(task.endTime) }}
								<div
									v-if="isTimeDefined(task.endTime)"
									class="task-viewer__calendar-time"
								>
									{{ formatTime(task.endTime) }}
								</div>
							</div>
							<div v-if="task.startTime && task.endTime">
								<div class="task-viewer__calendar-title">
									Total duration
								</div>
								{{ calendarDuration }}
							</div>
						</div>
					</div>

					<!-- ANCHOR Milestones -->
					<div class="task-viewer__panel-section task-viewer__milestones">
						<div class="task-viewer__panel-title">
							Milestones
							<VindiSpacer />
							<w-icon>
								mdi mdi-cog
							</w-icon>
						</div>
						<div
							class="task-viewer__no-items"
						>
							No milestones assigned
						</div>
					</div>

				</template>
			</aside>
		</section>
	</w-dialog>
</template>

<script lang="ts">
import Vue from 'vue';
import dayjs from 'dayjs';
import { marked } from 'marked';
import { mapState } from "vuex";
import { clone, cloneDeep } from 'lodash';
import { ViewTask, ViewTaskAttachment } from '~/typings/models';
import updateTask from '~/assets/query/viewer/updateTask.gql';
import moveTask from '~/assets/query/viewer/moveTask.gql';
import popTask from '~/assets/query/viewer/popTask.gql';
import removeLabel from '~/assets/query/viewer/removeLabel.gql';
import addLabel from '~/assets/query/viewer/addLabel.gql';
import removeAssignee from '~/assets/query/viewer/removeAssignee.gql';
import deleteTask from '~/assets/query/project/deleteTask.gql';
import addAssignee from '~/assets/query/viewer/addAssignee.gql';
import updateAttachment from '~/assets/query/viewer/updateAttachment.gql';
import deleteAttachment from '~/assets/query/viewer/deleteAttachment.gql';
import onAttachmentAdd from '~/assets/query/viewer/onAttachmentAdd.gql';
import onAttachmentUpdate from '~/assets/query/viewer/onAttachmentUpdate.gql';
import onAttachmentRemove from '~/assets/query/viewer/onAttachmentRemove.gql';
import { downloadURL, formatBytes, IMAGE_FILES, openFilePicker } from '~/src/helpers';

const NO_LIST = Symbol('no-list');

export default Vue.extend({
	name: 'TaskView',
	
	data: () => ({
		manager: null as any,
		toolbarExpanded: false,
		isEditingDesc: false,
		labelSelector: false,
		listSelector: false,

		// Editable fields
		summary: '',
		description: '',
		taskList: undefined as number|undefined|typeof NO_LIST,

		// Project configurations
		projectLists: [] as any[],

		// Attachments
		attachments: [] as ViewTaskAttachment[],
		bannerImage: undefined as ViewTaskAttachment|undefined,

		// Calendar
		calendarOption: [] as any[],
		calendarOptions: [
			{ title: 'Start date', field: 'startTime' },
			{ title: 'Due date', field: 'endTime' }
		]
	}),

	computed: {
		...mapState({
			task: 'taskView',
			isVisible: 'taskViewOpen'
		}),

		isLoading(): boolean {
			return this.task === undefined;
		},

		viewerStyle(): any {
			return {
				'--accent-color': this.task?.project?.accentColor
			};
		},

		canExpandToolbar(): boolean {
			return this.$store.state.expandToolbar;
		},

		computeToolbarClass(): any {
			return {
				'task-viewer__toolbar--expanded': this.toolbarExpanded && this.canExpandToolbar
			};
		},

		creationTime(): string {
			const createdAt = parseInt(this.task.createdAt);
			const dateFormat = this.$t('FULL_DATE_FORMAT') as string;

			return dayjs(createdAt).format(dateFormat);
		},

		taskListItems(): any[] {
			const lists = this.projectLists.map(list => {
				const isFull = list.taskLimit && list.taskCount >= list.taskLimit;

				return {
					label: isFull ? list.name + ' (Full)' : list.name,
					value: list.id,
					disabled: isFull
				};
			});

			return [
				{ label: 'Task unlisted', value: NO_LIST },
				...lists
			];
		},

		renderedDescription(): string {
			return this.task ? marked(this.description) : '';
		},

		currentList(): any {
			return this.taskListItems.find((list) => list.value == this.taskList);
		},

		isCurrentlyAssigned(): boolean {
			if(!this.task) {
				return false;
			}
			
			const profile = this.$store.state.profile;

			if(!profile) {
				return false;
			}

			return this.assigneeIds.includes(profile.id);
		},

		assigneeIds(): number[] {
			return this.task.assignees.map((assignee: any) => assignee.id);
		},

		labelIds(): number[] {
			return this.task.labels.map((label: any) => label.id);
		},

		calendarDuration(): string {
			if(!this.task.startTime || !this.task.endTime) {
				return '';
			}

			const duration = parseInt(this.task.endTime) - parseInt(this.task.startTime);

			return dayjs.duration(duration).humanize();
		},
	},

	watch: {
		isVisible() {
			this.toolbarExpanded = false;
		},

		task(value: ViewTask) {
			this.loadTaskData(value);
		},

		taskList(value, previous) {
			if(previous !== undefined && value !== undefined) {
				// Update the local taskCount values to reflect
				// the "full" status of the previous and next list.
				// The timeout is required for the menu to close.
				setTimeout(() => {
					if(value !== NO_LIST) {
						this.getTaskList(value).taskCount++;
					}

					if(previous !== NO_LIST) {
						this.getTaskList(previous).taskCount--;
					}
				}, 100);

				this.updateTaskList();
			}
		}
	},

	mounted() {
		this.loadTaskData(this.task);
	},

	beforeDestroy() {
		this.manager?.dispose();
	},

	methods: {

		loadTaskData(task: ViewTask) {
			if(!task) return;

			this.summary = task.summary;
			this.description = task.description;
			this.taskList = undefined;
			this.projectLists = cloneDeep(task.project.lists);
			this.attachments = cloneDeep(task.attachments);
			this.bannerImage = clone(task.bannerImage);

			// Workaround to prevent task list watcher
			// firing based on the previous task's list.
			this.$nextTick(() => {
				this.taskList = task.list?.id || NO_LIST;
			});

			// Recreate the subscription manager
			this.manager?.dispose();
			this.manager = this.$api.createManager();
			this.registerAttachmentSubscriptions();
		},

		// Update query helper function
		updateTask(details: any) {
			this.$api.query(updateTask, {
				id: this.task.id,
				details: details
			});
		},

		removeTask() {
			this.$api.query(deleteTask, {
				id: this.task.id
			});

			this.setTaskHidden();
		},

		setTaskHidden() {
			this.$store.commit('hideCurrentTask');
		},

		toggletoolbarExpansion() {
			this.$store.commit('setExpandToolbar', !this.canExpandToolbar);
		},

		getTaskList(id: number): any {
			return this.projectLists.find(list => list.id == id);
		},

		editDescription() {
			this.isEditingDesc = true;
			
			this.$nextTick(() => {
				const editor = (this.$refs.descEditor as any).editor;
				
				editor.focus();
				editor.execCommand('selectAll');
			});
		},

		updateSummary() {
			if(!this.summary) {
				this.summary = this.task.summary;
				return;
			}

			this.$store.commit('patchCurrentTask', {
				summary: this.summary
			});

			this.updateTask({
				summary: this.summary
			});
		},

		updateTaskList() {
			if(this.taskList == NO_LIST) {
				this.$api.query(popTask, {
					id: this.task.id
				});
			} else {
				this.$api.query(moveTask, {
					id: this.task.id,
					list: this.taskList
				});
			}
		},

		discardDescription() {
			this.isEditingDesc = false;
			this.description = this.task.description;
		},

		updateDescription() {
			this.isEditingDesc = false;

			this.$store.commit('patchCurrentTask', {
				description: this.description
			});

			this.updateTask({
				description: this.description
			});
		},

		addTaskLabel(label: any) {
			const labels = [ ...this.task.labels, label ];

			this.$store.commit('patchCurrentTask', {
				labels
			});

			this.$api.query(addLabel, {
				id: this.task.id,
				labelId: label.id
			});
		},

		removeTaskLabel(label: any) {
			const labels = this.task.labels.filter((someLabel: any) => someLabel.id != label.id);
			
			this.$store.commit('patchCurrentTask', {
				labels
			});

			this.$api.query(removeLabel, {
				id: this.task.id,
				labelId: label.id
			});
		},

		addTaskAssignee(member: any) {
			const assignees = [ ...this.task.assignees, member ];

			this.$store.commit('patchCurrentTask', {
				assignees
			});

			this.$api.query(addAssignee, {
				id: this.task.id,
				userId: member.id
			});
		},

		removeTaskAssignee(member: any) {
			const assignees = this.task.assignees.filter((assignee: any) => assignee.id != member.id);
			
			this.$store.commit('patchCurrentTask', {
				assignees
			});

			this.$api.query(removeAssignee, {
				id: this.task.id,
				userId: member.id
			});
		},

		toggleTaskPinned() {
			const shouldPin = !this.task.isPinned;

			this.$store.commit('patchCurrentTask', {
				isPinned: shouldPin
			});

			this.updateTask({
				isPinned: shouldPin
			});
		},

		requestFileUpload() {
			const endpoint = `attachment?project=${this.task.project.id}&task=${this.task.id}`;

			openFilePicker({ multiple: true }, (...files) => {
				files.map(file =>
					this.$api.upload(endpoint, file)
				);
			});
		},

		formatAttachmentSize(att: ViewTaskAttachment) {
			return formatBytes(att.fileSize);
		},

		openAttachment(file: any) {
			window.open(window.location.origin + file.filePath);
		},

		computePreviewStyle(att: ViewTaskAttachment) {
			const isImage = IMAGE_FILES.includes(att.extension);

			return isImage && {
				backgroundImage: `url(${att.filePath})`,
				color: 'transparent'
			};
		},

		formatUploader(att: ViewTaskAttachment): string {
			return att.uploadedBy?.fullName || 'Unknown';
		},

		detachAttachment(attachment: any) {
			if(this.bannerImage != null && attachment.id == this.bannerImage.id) {
				this.updateTask({
					bannerImage: null
				});
			}

			this.$api.query(updateAttachment, {
				id: attachment.id,
				details: {
					task: null
				}
			});
		},

		setCover(attachment: any) {
			this.$store.commit('patchCurrentTask', {
				bannerImage: attachment
			});

			this.updateTask({
				bannerImage: attachment.id
			});
		},

		removeCover() {
			this.$store.commit('patchCurrentTask', {
				bannerImage: null
			});

			this.updateTask({
				bannerImage: null
			});
		},

		renameAttachment(attachment: any) {
			this.$api.query(updateAttachment, {
				id: attachment.id,
				details: {
					name: this.attachments[attachment].name
				}
			});
		},

		deleteAttachment(attachment: any) {
			if(this.bannerImage != null && attachment.id == this.bannerImage.id) {
				this.updateTask({
					bannerImage: null
				});
			}
			
			this.$api.query(deleteAttachment, {
				id: attachment.id
			});
		},

		attachDuration(attachment: any): string {
			const uploadedAt = parseInt(attachment.uploadedAt);
			const now = Date.now();

			return dayjs.duration(uploadedAt - now).humanize(true);
		},

		hideAttachment(attachment: any) {
			this.$store.commit('patchCurrentTask', {
				attachments: this.task.attachments.filter((att: any) => att.id != attachment.id)
			});
		},

		downloadAttachment(attachment: any) {
			downloadURL(attachment.filePath, attachment.name);
		},

		async copyAttachmentLink(attachment: any) {
			await navigator.clipboard.writeText(window.location.origin + attachment.filePath);

			this.$waveui.notify({
				message: 'Copied link to clipboard',
				success: true
			});
		},

		updateCalendarValue(time: number, fieldName: string) {
			if(!time) return;

			this.$store.commit('patchCurrentTask', {
				[fieldName]: time.toString()
			});

			this.updateTask({
				[fieldName]: time.toString()
			});
		},

		clearCalendarValue(fieldName: string) {
			this.$store.commit('patchCurrentTask', {
				[fieldName]: null
			});

			this.updateTask({
				[fieldName]: null
			});

			this.calendarOption = [];
		},

		formatCalendarTimer(fieldName: string) {
			const value = this.getCalendarValue(fieldName);
			const now = Date.now();

			return dayjs.duration(value - now).humanize(true);
		},

		formatDate(time: string) {
			const date = dayjs(parseInt(time));
			const format = this.$t('DATE_FORMAT') as string;

			return date.format(format);
		},

		formatTime(time: string) {
			const date = dayjs(parseInt(time));
			const format = this.$t('TIME_FORMAT') as string;

			return date.format(format);
		},

		getCalendarValue(fieldName: string) {
			return parseInt(this.task[fieldName]);
		},

		isTimeDefined(value: string) {
			const date = dayjs(parseInt(value));

			return date.hour() > 0 || date.minute() > 0;
		},

		registerAttachmentSubscriptions() {
			const pid = this.task.project.id;

			// Add attachment
			this.manager.subscribe({
				query: onAttachmentAdd,
				variables: {
					id: pid
				},
				next: (result: any) => {
					const att = result.attachmentUploaded;

					if(att.task?.id != this.task.id) {
						return;
					}

					this.attachments.push(att);
				}
			});

			// Update attachment
			this.manager.subscribe({
				query: onAttachmentUpdate,
				variables: {
					id: pid
				},
				next: (result: any) => {
					const att = result.attachmentUpdated;
					const index = this.attachments.findIndex((a: any) => a.id == att.id);

					const isInTask = index !== -1;
					const belongsToTask = att.task?.id == this.task.id;

					if(isInTask && !belongsToTask) {
						this.attachments.splice(index, 1);
					} else if(!isInTask && belongsToTask) {
						this.attachments.push(att);
					} else if(isInTask && belongsToTask) {
						this.$set(this.attachments, index, att);
					}
				}
			});

			// Remove attachment
			this.manager.subscribe({
				query: onAttachmentRemove,
				variables: {
					id: pid
				},
				next: (result: any) => {
					const att = result.attachmentRemoved;
					const index = this.attachments.findIndex((a: any) => a.id == att.id);

					if(index !== -1) {
						this.attachments.splice(index, 1);

						console.log(this.attachments);
					}
				}
			});
		}
	}
});
</script>

<style lang="scss">

$toolbar-collapsed-width: 3rem;
$toolbar-expanded-width: 14rem;

.task-viewer-overlay {
	align-items: flex-start;
	overflow-y: scroll;
	inset: 0;
}

.w-card.task-viewer-dialog {
	background-color: unset;
	margin: 100px 0;

	.w-card__content {
		padding: 0;
	}
}

.task-viewer {
	position: relative;
	display: flex;

	&__loading {
		display: flex;
		align-items: center;
		justify-content: center;
		height: 100%;
	}
	
	&__toolbar,
	&__content,
	&__panel {
		min-height: 38rem;
	}

	&__content,
	&__panel {
		@include padding(5);

		flex: 1;
	}

	&__toolbar {
		@include transition(size);
		
		z-index: 12;
		flex-shrink: 0;
		width: $toolbar-collapsed-width;
		background-color: var(--color-misc-1);
		display: flex;
		flex-direction: column;

		.w-divider {
			@include margin(2, x);
			@include margin(1.5, y);

			border-color: rgba(255, 255, 255, 0.2);
		}
	}

	&__toolbar-container {
		@include padding(2.75, t);

		height: 100%;
		display: flex;
		flex-direction: column;
	}

	&__toolbar-contents {
		@include transition(shadow);
		@include transition(size);

		height: 100%;
		position: absolute;
		overflow-x: hidden;
		background-color: var(--color-misc-1);
		width: $toolbar-collapsed-width;
		z-index: 900;
		top: 0;
	}

	&__toolbar--expanded &__toolbar-contents {
		box-shadow: rgba(43, 43, 43, 0.45) 0 0 1.25rem;
		width: $toolbar-expanded-width;
	}

	&__toolbar--expanded &__toolbar-item:last-child .w-icon {
		transform: rotate(180deg);
	}

	&__toolbar-item {
		@include transition(colors);

		cursor: pointer;
		display: flex;
		align-items: center;
		width: $toolbar-expanded-width;
		font-size: 1.1rem;
		color: white;

		&:hover {
			background-color: var(--accent-color);
		}

		&:last-child {
			height: 3.75rem;
		}

		> * {
			flex-shrink: 0;
		}

		> .w-icon {
			@include transition(all);

			display: flex;
			flex-shrink: 0;
			align-items: center;
			justify-content: center;
			height: $toolbar-collapsed-width;
			width: $toolbar-collapsed-width;
		}
	}

	&__content {
		background-color: var(--color-shade-0);

		@include dark {
			background-color: var(--color-shade-2);
		}
	}

	&__panel {
		max-width: 14.5rem;
		background-color: var(--color-shade-2);

		@include dark {
			background-color: var(--color-shade-3);
		}
	}

	&__close {
		@include margin(-1.5, t);
		@include margin(-1.5, r);
		@include margin(3, b);
	}

	&__parent {
		@include font-size(sm);
		@include padding(2, b);

		color: #8b8b8b;
		cursor: pointer;
	}

	&__parent-summary {
		color: #363636;

		@include dark {
			color: #c4c4c4;
		}
	}

	&__row {
		display: flex;
		align-items: center;
		gap: 9px;
	}

	&__id {
		@include font-weight(bold);
		@include font-size(xl);

		color: var(--accent-color);
	}

	&__summary {
		flex: 1;

		.w-input__input-wrap {
			@include padding(1.5, l);
		}

		input {
			@include font-size(lg);

			padding-left: 0;
			color: #363636;
		}
	}

	&__created-at, &__created-by {
		@include font-size(sm);

		color: var(--accent-color);
	}

	&__created-at {
		color: #828282;
	}

	&__task-list {
		flex-grow: 0;
		padding: 0;
		width: 140px;

		.w-select__selection-wrap {
			padding-right: 0;
			padding-left: 0;
		}

		input {
			padding-left: 0;
		}
	}

	&__description {
		@include padding(4, t);

		min-height: 8.5rem;

		.CodeMirror {
			@include ring(var(--color-primary), 2);

			height: fit-content !important;
			margin-left: -8px;
			min-height: 80px;
		}

		.CodeMirror-lines {
			padding-left: 4px !important;
		}

		.CodeMirror-sizer {
			margin-bottom: unset !important;
		}
	}

	&__description-editor {
		@include margin(2, b);
	}

	&__description .CodeMirror-placeholder,
	&__description-placeholder {
		color: #828282 !important;
		font-style: italic;
	}

	&__description-preview,
	&__description-placeholder {
		@include padding(1.5, y);
	}

	&__section {
		@include margin(6, t);
	}

	&__section-title {
		@include font-weight(medium);
		@include font-size(lg);
		@include padding(1, b);

		border-bottom: 1px solid var(--color-shade-2);
	}

	&__attachments {
		@include padding(3, t);
	}

	&__attachment {
		@include rounded(lg);
		@include padding(2);

		display: flex;
		gap: 0.75rem;

		&:not(:first-child) {
			@include margin(0.5, t);
		}

		// &:not(:last-child) {
		// 	border-bottom: 1px solid var(--color-shade-2);
		// }
	}

	&__attachment-preview {
		@include rounded(lg);

		color: gray;
		display: flex;
		align-items: center;
		justify-content: center;
		height: 5rem;
		aspect-ratio: 3/2;
		background-color: var(--color-shade-2);
		background-size: cover;
		background-position: center;
	}

	&__attachment-info {
		flex: 1;
	}

	&__attachment-name {
		@include font-weight(medium);
		@include truncate;
		
		max-width: 20rem;
	}

	&__attachment-uploader {
		@include font-size(sm);
		@include truncate;
		
		color: gray;
		max-width: 20rem;
	}

	&__attachment-size {
		@include font-size(sm);

		color: gray;
	}

	&__attachment-options {
		align-self: flex-start;
	}

	&__panel-section:not(:last-child) {
		@include margin(8, b);
	}

	&__panel-title {
		@include font-size(base);
		@include font-weight(semibold);
		@include margin(1.5, b);

		display: flex;
		align-items: center;

		> .w-icon {
			@include transition(colors);

			cursor: pointer;

			&:hover {
				color: var(--accent-color);
			}
		}
	}

	&__label {
		@include margin(1, b);
		@include transition(all);
		
		cursor: pointer;
	}

	&__labels-list {
		@include padding(2);
	}

	&__no-items {
		@include font-size(sm);

		color: gray;
	}

	&__assignee {
		@include margin(1, t);
		@include margin(2, b);
		@include font-size(sm);

		display: flex;
		align-items: center;

		.avatar {
			@include margin(2, r);
		}

		> .w-icon {
			@include font-size(base);
			
			cursor: pointer;
		}
	}

	&__calendar-menu {
		.date-picker {
			border: none;
		}
	}

	&__calendar-options {
		@include padding(2, x);
		@include padding(2, b);

		justify-content: stretch;

		.w-radio__label {
			flex-grow: 1;
		}
	}

	&__calendar-card {
		@include rounded(lg);
		@include padding(2);
		@include font-weight(light);

		background-color: var(--color-shade-0);
		box-shadow: rgb(0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;
		border-left: 4px solid var(--accent-color);
		display: flex;
		flex-direction: column;
		gap: 1rem;
	}

	&__calendar-title {
		@include padding(0, b);
		@include font-weight(semibold);
		@include font-size(xs);

		text-transform: uppercase;
		opacity: 1;
	}

	&__calendar-time {
		color: var(--accent-color);
	}

	&__calendar-value {
		@include font-weight(thin);
		@include font-size(sm);
	}

	&__actions {
		.w-button {
			@include rounded(md);
			@include padding(3.75, y);
			@include padding(3, x);
			@include margin(2, b);
			@include font-weight(normal);

			justify-content: start;
			width: 100%;
		}

		.w-divider {
			@include margin(0.75, t);

			border-color: rgba(0, 0, 0, 0.1);
		}
	}
}
</style>