<template>
	<!-- change class to .master-note-edit to have it popup on the screen. 
		@keyup.esc="closeButtonAction()"  -->
	<div class="master-note-edit">

		<!-- Edit Menus  -->

		<div class="menu-top-half" :class="{ 'hide-text':(openNotes > 1) }">

			<div class="edit-button" v-on:click="colorpicker = true" data-tooltip="Text Color" data-position="bottom center">
				<i class="font icon"></i>
				<div class="font-color-bar" :style="{'background':lastUsedColor}"></div>
				<span>Color</span>
			</div>

			<div class="edit-button" v-on:click="toggleBold()" :data-tooltip="`Bold\n(CTRL + b)`" data-position="bottom center" :class="{'edit-active':activeBold}">
				<i class="bold icon"></i>
				<span>Bold</span>
			</div>

			<div class="edit-button" v-on:click="toggleItalic()" :data-tooltip="`Italic\n(CRTL + i)`" data-position="bottom center" :class="{'edit-active':activeItalics}">
				<i class="italic icon"></i>
				<span>Italic</span>
			</div>

			<div class="edit-button" v-on:click="toggleUnderline()" :data-tooltip="`Underline\n(CRTL + u)`" data-position="bottom center" :class="{'edit-active':activeUnderline}">
				<i class="underline icon"></i>
				<span>Underline</span>
			</div>

			<div class="edit-button" v-on:click="modifyCode('1.4em')" data-tooltip="Quote" data-position="bottom center" :class="{'edit-active':activeCode}">
				<i class="quote right icon"></i>
				<span>Quote</span>
			</div>

			<div class="edit-button" v-on:click="modifyFont('0.9em')" data-tooltip="Sub Title" data-position="bottom center" :class="{'edit-active':activeSubTitle}">
				<i class="small text height icon"></i>
				<span>Small Text</span>
			</div>

			<div class="edit-button" v-on:click="modifyFont('1.4em')" data-tooltip="Title" data-position="bottom center" :class="{'edit-active':activeTitle}">
				<i class="text height icon"></i>
				<span>Title</span>
			</div>

			<div class="edit-button" v-on:click="removeFormatting()" data-tooltip="Remove Formatting" data-position="bottom center">
				<i class="remove format icon"></i>
			</div>

			<div class="edit-divide"></div>

			<div class="edit-button" v-on:click="indentText" :data-tooltip="`Indent\n(TAB)`" data-position="bottom center">
				<i class="indent icon"></i>
				<span>Indent</span>
			</div>
			<div class="edit-button" v-on:click="outdentText" :data-tooltip="`Un-Indent\n(SHIFT + TAB)`" data-position="bottom center">
				<i class="outdent icon"></i>
			</div>

		</div>

		<div class="menu-bottom-half" :class="{ 'hide-text':(openNotes > 1) }">

			<!--
			<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/table`)" data-tooltip="Insert Table" data-position="bottom center">
				<i class="border all icon"></i>
			</div> -->


			<div class="edit-button" v-on:click="toggleList('ul')" :data-tooltip="`Task List\n(CTRL + SHIFT + 8)`" data-position="top center" :class="{'edit-active':activeToDo}">
				<i class="tasks icon"></i>
				<span>To-Do</span>
			</div>
			<div class="edit-button" v-on:click="toggleList('ol')" :data-tooltip="`Ordered List\n(CTRL + SHIFT + 9)`" data-position="top center" :class="{'edit-active':activeList}">
				<i class="list ol icon"></i>
				<span>List</span>
			</div>

			<div class="edit-divide"></div>
			
			<div class="edit-button" v-on:click="insertDivide()" data-tooltip="Insert Divide" data-position="top center">
				<i class="grip lines icon"></i>
				<span>Divide</span>
			</div>


			<div class="edit-divide"></div>

			<!-- 				
			<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/colors`)" data-tooltip="Note Color" data-position="top center" :style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText']}">
				<i class="paint brush icon"></i>
			</div> -->
			<!-- <div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/tags`)" data-tooltip="Tags" data-position="top center">
				<i class="tags icon"></i>
			</div> -->
			<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/images`)" data-tooltip="Images" data-position="top center">
				<i class="image icon"></i>
				<span>Images</span>
			</div>

			<file-upload-button 
				data-tooltip="Upload File" data-position="top center"
				class="edit-button" 
				:noteId="noteid" />

			<div class="edit-divide"></div>

			<div class="edit-button" v-on:click="$router.push(`/notes/open/${noteid}/menu/options`)" data-tooltip="More Options" data-position="top center">
				&nbsp;&nbsp;
				<i class="ellipsis horizontal icon"></i>
				&nbsp;&nbsp;
			</div>

			<div class="edit-divide"></div>

			<div class="edit-button" v-on:click="undoCustom()" :data-tooltip="`Undo\n(CTRL + z)`" data-position="top center">
				<i class="reply icon"></i>
			</div>

			<div class="edit-button done-button" v-on:click="closeButtonAction()" :data-tooltip="`Close\n(ESC)`" data-position="top center">
				<!-- <i class="green close icon"></i> -->
				<span class="ui green text">Done</span>
			</div>
			
		</div>

		<div class="input-container-wrapper"
			:class="{ 'side-menu-open':sideMenuOpen }">

			<!-- Squire box grows -->
			<div class="note-wrapper">

				<!-- Loading indicator  -->
				<transition name="fade">
					<div v-if="loading && forceShowLoading" class="loading-note" :style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText']}">
						<div class="loading-text">
							<loading-icon :message="loadingMessage" />
						</div>
					</div>
				</transition>

				<!-- Title input area  -->
				<textarea 
					ref="titleTextarea"
					v-on:keyup="titleResize"
					v-on:keydown="titleResize"
					@keydown.enter.exact.prevent="editor.focus(); editor.moveCursorToEnd()"
					rows="1"
					:style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText'] }"
					v-on:blur="save" type="text" v-model="noteTitle" placeholder="Title" class="stealth-input glint">
				</textarea>

				<!-- close button giant -->
				<div v-if="!$store.getters.getIsUserOnMobile" class="large-close-button" v-on:click="closeButtonAction()">
					<i class="fitted green close icon"></i>
				</div>

				<!-- tags on the side, only show on desktop -->
				<div class="note-mini-tag-area"
					v-on:click="$router.push(`/notes/open/${noteid}/menu/tags`)" 
					:style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText'] }">

					<span class="add-mini-tag" v-if="allTags.length == 0">
						<i class="tags icon"></i>Add Tags
					</span>
					<span v-for="tag in allTags" class="active-mini-tag">
						#{{ tag }}
					</span>
					<span class="active-mini-tag" v-if="allTags.length > 0">
						+
					</span>

					<span class="status-menu" v-on:click=" hash=0; save()">

						<span v-if="diffsApplied > 0">
							+{{ diffsApplied }} Unsaved Changes
						</span>

						<span v-if="usersOnNote > 1" :data-tooltip="`Viewers`" data-position="left center">
							<i class="green eye icon"></i> {{ usersOnNote }}
						</span>

						<span v-if="statusText == 'modified'" data-position="left center" data-tooltip="Modified">
							<i class="grey asterisk icon"></i>
						</span>
						<span v-if="statusText == 'saving'" data-position="left center" data-tooltip="Saving">
							<i class="grey upload icon"></i>
						</span>
						<span v-if="statusText == 'saved'" data-position="left center" data-tooltip="Saved">
							<i class="grey check icon"></i>
						</span>

					</span>
					
				</div>

				<!-- Squire Box -->
				<div 
					id="squire-id" 
					class="squire-box" 
					ref="squirebox" 
					:style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText'] }"
					placeholder="Type Note Here"></div>
				
			</div>

		</div>

		

		<!-- color picker -->
		<color-tooltip 
			v-if="colorpicker" 
			:last-used-color="lastUsedColor"
			v-on:color="color => modifyColor(color)"
			v-on:close="colorpicker = false"
		/>

		<!-- Side slide menus for colors, tags, images and other options -->
<!-- 		<side-slide-menu v-if="colors" v-on:close="colors = false" name="colors">
			<color-picker
				@changeColor="onChangeColor"
				@close="colors = false; $router.go(-1)"
				:style-object="styleObject"
			/>
		</side-slide-menu> -->

		<!-- tag edit menu -->
		<side-slide-menu v-if="tags" v-on:close="tags = false; fetchNoteTags()" name="tags">
			<div class="ui basic segment">
				<note-tag-edit :noteId="noteid" :key="'tags-for-note-'+noteid"/>
			</div>
		</side-slide-menu>

		<!-- images menu -->
		<side-slide-menu v-if="images" v-on:close="images = false" name="images">
			<div class="ui basic segment">
				<simple-attachment-note
					:note-id="noteid" 
					:squire-editor="editor">
				</simple-attachment-note>
			</div>
		</side-slide-menu>

		<side-slide-menu v-if="options" v-on:close="options = false" name="note-options">
			<div class="ui basic padded segment">
				<div class="ui compact stackable grid">

					<div class="eight wide column">
						<div class="ui dividing header">
							Note Options
						</div>
		 				<div class="ui labeled icon fluid basic button" v-on:click="onToggleArchived()">
		 					<i class="archive icon" :class="{'green':(archived == 1)}"></i>
							<span v-if="archived == 1">Un-Archive Note</span>
							<span v-if="archived != 1">Archive Note</span>
						</div>
						<div class="ui labeled icon fluid basic button" v-on:click="onTogglePinned">
							<i class="pin icon" :class="{'green':(pinned == 1)}"></i>
							<span v-if="pinned == 1">Un-Pin Note</span>
							<span v-if="pinned != 1">Pin Note</span>
						</div>
					</div>

					<div class="eight wide column">
						<div class="ui dividing header">
							List Options
						</div>
						<div class="ui labeled icon fluid basic button" v-on:click="sortList">
							<i class="sort amount up icon"></i>
							Sort List (Complete to bottom)
						</div>
						<div class="ui labeled icon fluid basic button" v-on:click="uncheckAllListItems">
							<i class="list ul icon"></i>
							Uncheck All
						</div>
						<div class="ui labeled icon fluid basic button" v-on:click="deleteCompletedListItems">
							<i class="trash icon"></i>
							Delete Checked
						</div>
					</div>

					<div class="eight wide column">
						<div class="ui dividing header">
							Calculate Line
						</div>
						<p>
							Calculates algebra before '='
						</p>
						<div class="ui labeled icon fluid basic button" v-on:click="calculateMath">
							<i class="calculator icon"></i>
							Calculate Simple Math
						</div>
					</div>

					<div class="eight wide column">
						<!-- data-tooltip="Files on note" -->
						<div class="ui dividing header">
							Note Attachments & Links
						</div>
						<p>
							Attachment & Link Count {{ attachmentCount }}
						</p>
						<div v-on:click="openEditAttachment"  class="ui labeled icon fluid basic button">
							<i class="folder icon"></i>
							View all Attachments & Links 
						</div>
					</div>

					<color-picker
						@changeColor="onChangeColor"
						@close="colors = false; $router.go(-1)"
						:style-object="styleObject"
					/>

					<div class="sixteen wide column" v-if="rawTextId > 0">
						<div class="ui dividing header">
							Share Note
						</div>
						<share-note-component 
							:note-id="noteid"
							:raw-text-id="rawTextId"
							:share-username="shareUsername"
						/>
					</div>
				</div>
			</div>
		</side-slide-menu>

		<!-- create table option  -->
		<side-slide-menu v-if="table" v-on:close="table = false;" name="table" :style-object="styleObject">
			<div class="ui basic segment">
				<h2>Insert Table</h2>
				<div class="table-tic-table">
					<div v-for="i in 10">
						<div v-for="j in 10" class="tabletic" v-on:click="insertTable(i,j)">
						</div>
					</div>
				</div>
				
			</div>
		</side-slide-menu>

		<!-- Show side shades if user is on desktop only -->
<!-- 		<div class="full-focus-shade shade1"
			:class="{ 'fade-me-out':sizeDown }"
			v-on:click="closeButtonAction()"></div> -->

	</div>
</template>

<script>

	const Squire = require('../assets/squire.js')

	import axios from 'axios'
	// const crypto = require('crypto')
	const DiffMatchPatch = require('../../../server/helpers/DiffMatchPatch')
	const dmp = new DiffMatchPatch.diff_match_patch()

	import SquireButtonFunctions from '@/mixins/SquireButtonFunctions.js'
	
	export default {
	name: 'NoteInputPanel',
		props: [ 'noteid', 'position', 'openMenu', 'urlData', 'openNotes'],
		components:{
			'note-tag-edit': () => import('@/components/NoteTagEdit.vue'),
			'color-picker': () => import('@/components/ColorPicker.vue'),
			'file-upload-button': () => import('@/components/FileUploadButton.vue'),
			// 'delete-button': () => import('@/components/NoteDeleteButtonComponent.vue'),
			'side-slide-menu': () => import('@/components/SideSlideMenuComponent.vue'),
			'simple-attachment-note': () => import('@/components/SimpleAttachmentNoteComponent.vue'),
			'share-note-component': () => import('@/components/ShareNoteComponent.vue'),

			'color-tooltip':require('@/components/TextColorTooltipComponent.vue').default,
			'nm-button':require('@/components/NoteMenuButtonComponent.vue').default,
			'loading-icon':require('@/components/LoadingIconComponent.vue').default,
		},
		mixins:[ SquireButtonFunctions ],
		data(){
			return {
				loading: true,
				forceShowLoading: false,
				loadingMessage: 'Loading Note',
				currentNoteId: 0,
				modified: false,
				noteText: '',
				noteTitle: '',
				rawTextId: 0,
				created: '',
				updated: '',
				shareUsername: null,
				// diffNoteText: '',
				statusText: 'saved',
				lastNoteHash: null,
				saveDebounce: null, //Prevent save from being called numerous times quickly
				updated: 'Never',
				lastInteractionTimestamp:null, //Tracks when note was loaded and last saved/refreshed
				editDebounce: null,
				textChangedDebounce: null,
				keyPressesCounter: 0, //Determine keys pressed between saves
				pinned: 0,
				archived: 0,
				attachmentCount: 0,
				styleObject: { 'noteText':null,'noteBackground':null, 'noteIcon':null, 'iconColor':null }, //Style object. Determines colors and badges

				sizeDown: false, //Used to animate close state

                //Settings vars
                lastVisibilityState: null,

                //All the squire settings
                editor: null,
                usersOnNote: 0,

                sideMenuOpen: false,
                tags: false,
                colors: false, 
                images: false,
                options: false,
                colorpicker: false,
                table: false,

                //Diff text/sync text variables
                diffTextTimeout: null,
                diffsApplied: null,

                //Used to restore caret position
                lastRange: null,
                startOffset: 0,

                //Tag Display
                allTags: [],
                noteTags: [],
			}
		},
		watch: {
			urlData(newVal, oldVal){

				//Handle changes in URL to 

				if(newVal.id == undefined || newVal.id != this.noteid){
					// this.closeButtonAction()
				}

				//Reset all note menus on URL change
				this.sideMenuOpen = false
				this.colors = false
				this.tags = false
				this.options = false
				this.images = false
				this.table = false

				//If a menu value is set, open it
				if(newVal.openMenu && newVal.id == this.noteid){
					//Only modify menu boolean if its defined
					if(typeof this[newVal.openMenu] == 'boolean'){
						this.sideMenuOpen = true
						this[newVal.openMenu] = true
					}
				}
			}
		},
		beforeMount(){

			this.$bus.$on('new_file_upload', ({noteId, imageCode}) => {
				if(this.noteid == noteId && this.editor){
					this.editor.moveCursorToEnd()
					this.editor.insertHTML(imageCode)
					this.save()
				}
			})

			this.$bus.$on('close_note_by_id', (noteId) => {
				if(noteId == this.noteid){
					this.closeButtonAction()
				}
			})
		},
		beforeDestroy(){

			this.$io.emit('leave_room', this.rawTextId)

			this.$bus.$off('new_file_upload')

			this.destroyWebSockets()

			document.removeEventListener('visibilitychange', this.checkForUpdatedNote)

			//Obliterate squire instance
			this.editor.destroy()
			
			// trigger save actions and reindex
			this.close()

		},
		mounted: function() {

			//Show loading if note has not loaded in 500ms
			setTimeout(()=>{
				this.forceShowLoading = true
			}, 500)

			document.addEventListener('visibilitychange', this.checkForUpdatedNote)

			//Init squire as early as possible
			if(this.editor && this.editor.destroy){
				this.editor.destroy()
			}
			this.editor = new Squire( this.$refs.squirebox, {blockTag: 'p' })

			this.$nextTick(() => {
				//Setup Squire first chance we get
				this.loadNote(this.noteid)
			})
		},
		methods: {
			testModify(){
				const text = document.getElementById('squire-id').children[0].innerHTML
				const prepended = 'Hello-> ' + text
				document.getElementById('squire-id').children[0].innerHTML = prepended

				const text1 = document.getElementById('squire-id').children[2].innerHTML
				const prepended1 = 'Hey-> ' + text1
				document.getElementById('squire-id').children[2].innerHTML = prepended1
			},
			simulateTyping(index = 0){

				const words = ['lets','see','how','big','of','a','list','we','can','make','and','if','we','can','simulate','multiple','users','typing','its','probably','going','to','be','a','shitty','shit','show','but','whatever','~','You all','ever','seen','a','full','size','zebra','eat','a','big','fat','mound','of','grass','let','me','tell','you','man,','those','freaking','things','can','chew.','I','mean','like','really','chew.','Not','just','a','little,','but','a','lot.','~','Do not','believe','me.','Shoot','on','down','to','your','local','zoo','with','a','fat','mound','of','grass.','~','In','other','news,','I','really','enjoy','testing','things.','I am','just','going','to','keep','on','typing','until','its','so','annoying','that','you','give','up','on','trying','to','type','other','things.','~','Other','people','do not','get','to','type!','Only','me!','Fuck','off','other','users.','Its','all','about','me','up','in','here.','And','~','Zebra','Grass.',
				]

				const nextWord = words[index % (words.length)] + ' '
				let letterObjects = []
				let totalTime = 0
				nextWord.split('').forEach(letter => {

					const letterTime = Math.floor(Math.random() * 80) + 20
					totalTime += letterTime

					setTimeout(() => {
						const newText = this.getText().slice(0,-8)
						if(letter == ' '){
							letter = ' <br></p>'
						}
						if(letter == '~'){
							letter = '<br></p><p><br></p><p><br></p>'
						}
						const addedLetter = newText + letter
						this.setText(addedLetter)
						this.onKeyup()

					}, totalTime)
				})

				setTimeout(() => {

					if(index < words.length-1){
						const more = index + 1
						this.simulateTyping(more)
					}

				}, totalTime + 40)
			},
			fetchNoteTags(){
				axios.post('/api/tag/fornote', {'noteId': this.noteid})
				.then(({data}) => {

					//Setup note tags from string
					this.allTags = data.tags ? data.tags.split(',') : []
					
				})
			},
			initSquire(){
				
				//Set up squire and load note text
				this.setText(this.noteText)

				//focus on open, not on mobile, it causes the keyboard to pop up, thats annoying
				if(!this.$store.getters.getIsUserOnMobile){
					this.editor.focus()
					this.editor.moveCursorToEnd()
				}

				//Set up websockets after squire is set up
				setTimeout(() => {
					this.setupWebSockets()
				}, 500)

				this.editor.addEventListener('cursor', e => {

					//Save range to replace cursor if someone else makes an update
					this.lastRange = e.range
					this.startOffset = parseInt(e.range.startOffset)
					return
				})

				//Change button states on editor when element is active
				//eg; Bold button turns green when on bold text
				this.editor.addEventListener('pathChange', e => this.pathChangeEvent(e))

				//Click Event - Open links when clicked in editor or toggle checks
				this.editor.addEventListener('click', e => {

					//Link clicked in editor - open link
					if(e.target.nodeName == 'A' && e.target.href){
						window.open(e.target.href)
					}

					//List Item clicked in editor - toggle link state
					if(e.target.nodeName == 'LI'){

						let el = e.target

						//If the offset is triggered with a negative offset, it means the before element was clicked
						if(e.offsetX < -5){

							//Area before element was clicked, they clicked the checkbox
							if (el.className === 'active'){
								el.className = 'inactive';
							} else {
								el.className = 'active';
							}
							//Trigger keyup event to save list changes
							this.onKeyup(e)

							//Will hide keyboard if clicked on mobile
							if(this.$store.getters.getIsUserOnMobile){

								setTimeout(() => {

									document.activeElement.blur()
									e.preventDefault()
									return

								}, 25)

							}
						}

						
					}
					
				})

				this.editor.addEventListener('keydown', event => {

					//Tab to increase quote level, tab + shigt to decrease quote level
					const keyCode = event.key
					if(keyCode == 'Tab'){

						if(event.shiftKey){
							this.outdentText()
						} else {
							this.indentText()
						}
						
						event.preventDefault()
						return false
					}

					//Save on pressing CTRL/CMD + S
					if(keyCode == 's' && (event.ctrlKey || event.metaKey) ){

						this.$bus.$emit('notification', 'Note Saved')
						this.save()
						
						event.preventDefault()
						return false
					}

					//Prevent new list items from having 
					this.$nextTick( () => {
						//Wait a moment to get item under cursor
						let selection = this.editor.getSelection()
						let container = selection.commonAncestorContainer

						//If user hit enter on a list, make sure the next list item isn't active
						if(container.nodeName == 'LI' && event.keyCode == 13 && container.classList){
							container.classList.remove('active')
						}
					})
				})

				//Bind event handlers
				this.editor.addEventListener('keyup', event => {

					this.onKeyup(event)
				})

				// this.editor.addEventListener("dragstart", e => {
				// 	console.log('Dragging')
				// 	console.log(e)
				// 	if(){}
				// });

				//Show and hide additional toolbars
				// this.editor.addEventListener('focus', e => {
				// })
				// this.editor.addEventListener('blur',  e => {
				// })
			},
			openEditAttachment(){

				this.$router.push('/attachments/note/'+this.currentNoteId)
			},
			onTogglePinned(){

				if(this.pinned == 0){
					this.pinned = 1
				} else {
					this.pinned = 0;
				}
				//Update last note hash, this will tell note to save next update
				this.lastNoteHash = 0
				this.save()
			},
			onToggleArchived(){

				if(this.archived == 0){
					this.archived = 1
				} else {
					this.archived = 0;
				}
				//Update last note hash, this will tell note to save next update
				this.lastNoteHash = 0
				this.save()
			},
			onChangeColor(newStyleObject){

				//Set new style object for note, page will use some styles, styles will be saved to database
				this.styleObject = newStyleObject

				this.lastNoteHash = 0 //Update hash to force note update on next save
				this.save()
			},
			loadNote(noteId){

				//Generate a random loading message
				let mod = ['Gently','Calmly','Lovingly','Quickly','Diligently','','','','','','','','','','','','','','']
				let doing = ['Loading','Loading','Getting','Fetching','Grabbing','Sequencing','Organizing','Untangling','Processing','Refining','Extracting','Fusing','Pruning','Expanding','Enlarging','Transfiguring','Quantizing','Ingratiating','Lumping']
				let thing = ['Note','Note','Note','Note','Data','Text','Document','Algorithm','Buffer','Client','Download','File','Frame','Graphics','Hardware','HTML','Interface','Logic','Mainframe','Memory','Media','Nodes','Network','Chaos']

				let p1 = mod[Math.floor(Math.random() * mod.length)]
				let p2 = doing[Math.floor(Math.random() * doing.length)]
				let p3 = thing[Math.floor(Math.random() * thing.length)]
				this.loadingMessage = `${p1} ${p2} ${p3}`
				
				//Component is activated with NoteId in place, lookup text with associated ID
				if(this.$store.getters.getLoggedIn){
					axios.post('/api/note/get', { 'noteId': this.noteid })
					.then(response => {

						//Block notes you don't have access to from opening
						if(response.data === false){
							this.$bus.$emit('notification', 'Error opening Note')
							this.close()
							return
						}

						//Setup all responsive vue data 
						this.setupLoadedNoteData(response)

						this.loading = false

						this.$nextTick(() => {

							//Adjust note title size after load
							this.titleResize()
							this.initSquire()
						})

					})
					.catch(error => { this.$bus.$emit('notification', 'Failed to Open Note') })
				} else {
					console.log('Could not fetch note')
				}
			},
			setupLoadedNoteData(response){
				//All the data returned by the server, setup locally in vue component

				//Set up local data
				this.currentNoteId = this.noteid
				this.rawTextId = response.data.rawTextId
				this.shareUsername = response.data.shareUsername

				this.created = response.data.created
				this.updated = response.data.updated
				this.lastInteractionTimestamp = +new Date
				this.noteTitle = ''
				if(response.data.title){
					this.noteTitle = response.data.title
				}

				this.noteText = response.data.text
				this.lastNoteHash = this.hashString( response.data.text )
				// this.diffNoteText = response.data.text

				//Setup note tags
				this.allTags = response.data.tags ? response.data.tags.split(','):[]

				//Set up note colors
				if(response.data.color){
					this.styleObject = JSON.parse(response.data.color)
				}
				
				if(response.data.pinned != null){
					this.pinned = response.data.pinned
				}
				this.archived = response.data.archived
				this.attachmentCount = response.data.attachment_count

				return true

			},
			//Called on squire event for keyup
			diffText(event){

				//Diff the changed lines only

				let oldText = this.noteText
				// let newText = this.getText()
				let newText = document.getElementById('squire-id').innerHTML

				const diff = dmp.diff_main(oldText, newText)
				// dmp.diff_cleanupSemantic(diff)
				const patch_list = dmp.patch_make(oldText, newText, diff);
				const patch_text = dmp.patch_toText(patch_list);

				if(patch_text == ''){ return }

				//Save computed diff text
				this.noteText = newText

				let newPatch = {
					id: this.rawTextId,
					diff: patch_text,
				}

				this.$io.emit('note_diff', newPatch)
			},
			patchText(incomingPatchs){
				return new Promise((resolve, reject) => {

					if(incomingPatchs == null){ return resolve(true) }
					if(incomingPatchs.length == 0){ return resolve(true) }

					// let currentText = this.getText()
					let currentText = document.getElementById('squire-id').innerHTML

					//Convert text of all new patches into patches array
					let patches = []
					incomingPatchs.forEach(patch => {

						if(patch.time <= this.updated){
							return
						}

						patches.push(...dmp.patch_fromText(patch.diff))
					})
					
					if(patches.length == 0){
						return resolve(true)
					}

					var results = dmp.patch_apply(patches, currentText);
					let newText = results[0]

					this.noteText = newText
					// this.editor.setHTML(newText)
					document.getElementById('squire-id').innerHTML = newText

					return resolve(true)
				})
			},
			onKeyup(event){

				this.statusText = 'modified'

				// Small debounce on diff generation
				clearTimeout(this.diffTextTimeout)
				this.diffTextTimeout = setTimeout(() => {
					this.diffText()
				}, 25)

				//Save after x seconds
				clearTimeout(this.editDebounce)
				this.editDebounce = setTimeout(() => {
					this.save()
				}, 5 * 1000)

				//Save after x keystrokes
				this.keyPressesCounter = (this.keyPressesCounter + 1)
				if(this.keyPressesCounter > 60){
					this.keyPressesCounter = 0
					this.save()
				}

			},
			save(force = false){
				return new Promise((resolve, reject) => {
					//Clear other debounced events to prevent double calling of save
					// clearTimeout(this.editDebounce)

					if(this.statusText == 'saving'){
						return resolve(true)
					}

					//Don't save note if its hash doesn't change
					const currentNoteText = this.getText()
					const currentHash = this.hashString( currentNoteText )
					if( this.lastNoteHash == currentHash){
						this.statusText = 'saved'
						return resolve(true)
					}

					//If user accidentally clears note, it won't delete it
					if(currentNoteText == ''){
						return resolve(true)
					}

					//tell websockets to truncate history at this save
					this.$io.emit('truncate_diffs_at_save', {'rawTextId':this.rawTextId, 'hash':currentHash })
					
					const postData = {
						'noteId': this.currentNoteId,
						'title': this.noteTitle,
						'text': currentNoteText,
						'color': JSON.stringify(this.styleObject), //Save little json color object
						'pinned': this.pinned,
						'archived': this.archived,
						'hash': currentHash,
					}

					this.statusText = 'saving'
					axios.post('/api/note/update', postData).then( response => {
						this.statusText = 'saved'
						this.updated = +new Date
						this.lastInteractionTimestamp = +new Date
						this.modified = true
						this.diffsApplied = 0

						//Update last saved note hash
						this.lastNoteHash = currentHash
						return resolve(true)
					})
					.catch(error => { this.$bus.$emit('notification', 'Failed to Save Note') })
				})
			},
			checkForUpdatedNote(){

				const now = +new Date
				//Only check every 3 seconds
				const checkForUpdateTimeout = now - this.lastInteractionTimestamp > (2 * 1000)

				//If user leaves page then returns to page, reload the first batch
				if(this.lastVisibilityState == 'hidden' && document.visibilityState == 'visible' && checkForUpdateTimeout){
					
					//Focus Regained on Note, check for update
					axios.post('/api/note/get', { 'noteId': this.noteid })
					.then(response => {

						const serverTextHash = this.hashString( response.data.text )

						if(this.lastNoteHash != serverTextHash){
							// console.log('note was changed UPDATE THAT BITCH!!!!')
							this.setupLoadedNoteData(response)

							//Manually set squire text to show
							this.setText(this.noteText)
						}

					})

				}

				//Keep track of visibility change and last interaction time
				this.lastVisibilityState = document.visibilityState
				this.lastInteractionTimestamp = +new Date
				
			},
			hashString(inText){

				let text = this.noteTitle + inText

				let hash = 0;
				if (text == null || text.length == 0) {
					return hash;
				}

				for (let i = 0; i < text.length; i++) {
					let char = text.charCodeAt(i);
					hash = ((hash<<5)-hash)+char;
					hash = hash & hash; // Convert to 32bit integer
				}

				return hash;
			},
			closeButtonAction(playAnimation = false){
				this.sizeDown = playAnimation
				const animationTimeout = (playAnimation ? 300 : 0)
				//This timeout allows animation to play before closing 
				setTimeout(() => {
					// this.$router.push('/notes')
					this.close()
				}, animationTimeout)
			},
			close(){

				// force = true

				// console.log(`Close Note ${this.noteid} -> force: ${force}, modified: ${this.modified}`)

				//Skip everything if foce close is true. Note will just die. 
				if(this.currentNoteId == 0){ return }

				this.loadingMessage = 'Saving...'
				this.loading = true

				this.save().then( result => {

					//If note was modified, trigger reindex on close
					if(this.modified){
						axios.post('/api/note/reindex')
					}

					this.$bus.$emit('close_active_note', {
						noteId: this.noteid, modified: this.modified
					})
					return
				})
			},
			destroyWebSockets(){
				// this.$io.removeListener('past_diffs')
				// this.$io.removeListener('update_user_count')
				// this.$io.removeListener('incoming_diff')
			},
			setupWebSockets(){

				//Tell server to push this note into a room
				this.$io.emit('join_room', this.rawTextId )

				this.$io.on('update_user_count', userCount => {
					this.usersOnNote = userCount
				})

				//Apply all diffs since last save
				this.$io.on('past_diffs', diffSinceLastUpdate => {

					if(diffSinceLastUpdate != null){
						this.diffsApplied = diffSinceLastUpdate.length
						// console.log('Got Diffs Total -> ', diffSinceLastUpdate)
					}
					this.patchText(diffSinceLastUpdate)
				})

				this.$io.on('incoming_diff', incomingDiff => {

					//Save current caret position
					//Find index of child element based on past range
					const element = window.getSelection().getRangeAt(0).startContainer.parentNode
					const textLines = document.getElementById('squire-id').children
					const childIndex = [...textLines].indexOf(element)

					this.patchText([incomingDiff])
					.then(() => {

						if(childIndex == -1){
							console.log('Cursor position lost. Div being updated was lost.')
							return
						}

						//Reset caret position
						//Find child index of old range and create a new one
						let allChildren = document.getElementById('squire-id').children
						const newLine = allChildren[childIndex].firstChild
						let range = document.createRange()
						range.setStart(newLine, this.startOffset)
						range.setEnd(newLine, this.startOffset)
						this.editor.setSelection(range)
					})
				})

			},
			titleResize(){
				//Resize the title field
				let element = this.$refs.titleTextarea
				if(element){

					element.style.height = 'auto'
	      			element.style.height = (element.scrollHeight) +'px'
				}
			},
		}
	}
</script>

<style type="text/css" scoped>

	.status-menu {
		position: absolute;
		right: 10px;
		z-index: 1019;
		text-align: right;
	}

	.font-color-bar {
		/*width: calc(100% - 8px);*/
		height: 3px;
		position: absolute;
		bottom: 2px;
		right: 4px;
		left: 4px;
		z-index: 0;
		background: linear-gradient(
	        45deg,
	        rgba(255, 0, 0, 1) 0%,
	        rgba(208, 222, 33, 1) 20%,
	        rgba(63, 218, 216, 1) 40%,
	        rgba(28, 127, 238, 1) 60%,
	        rgba(186, 12, 248, 1) 80%,
	        rgba(255, 0, 0, 1) 100%
	    );
	    overflow: hidden;
	}

	.large-close-button	{
		position: absolute;
		min-height: 55px;
		top: 0px;
		right: 0px;
		font-size: 23px;
		display: flex;
		justify-content: center;
		align-items: center;
		padding: 0 20px 0 10px;
		cursor: pointer;
	}

	.full-focus-shade {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background-color: var(--small_element_bg_color);
		z-index: 999;
		cursor: pointer;
		opacity: 0.6;
	}

	/* squire styles */
	.input-container-wrapper {
		position: absolute;
		top: 0;
		bottom: 0;
		left: 0;
		right: 0;
		overflow-y: scroll;
		overflow-x: hidden;
		scrollbar-width: none;
		scrollbar-color: transparent transparent;
		overscroll-behavior: contain;

		background-color: var(--border_color);
	}
	.note-wrapper {
		background-color: var(--border_color);
		position: relative;
		margin: 50px auto;

		max-width: 1100px;
	}

		.note-mini-tag-area {
			width: 100%;
			padding: 5px 15px 0 15px;
			cursor: pointer;
			position: relative;
			background: var(--small_element_bg_color);
		}
		.add-mini-tag {
			color: var(--border_color);
		}
		.active-mini-tag {
			display: inline-block;
			opacity: 0.9;
			color: var(--main-accent);
		}
		.active-mini-tag + .active-mini-tag {
			margin-left: 15px;
		}


	@keyframes blinker {
		50% {
			opacity: 0.2;
		}
	}

	/*
	
	Edit Menu Styles START
	
	*/
		.menu-top-half, .menu-bottom-half {
			display: flex;
			justify-content: center;
			position: absolute;
			z-index: 1001;
			background-color: green;
			border-radius: 3px;
			padding: 5px 5px;
			background-color: var(--menu-background);

			left: 0;
			right: 0;
		}
		.menu-top-half{
			top: 0;
		}
		.menu-bottom-half {
			bottom: 0;
		}
		.menu-top-half.hide-text .edit-button > span:not(.ui), 
		.menu-bottom-half.hide-text .edit-button > span:not(.ui) 
		{
			display: none;
		}
		.edit-button {
			background-color: var(--small_element_bg_color);
			color: var(--menu-text);
			display: inline-block;
			border-radius: 3px;
			cursor: pointer;
			font-size: 1em;
			box-shadow: 0 0 1px 0 #c4c4c4;
			margin: 0 3px 0;
			padding: 6px 12px 0;
			text-align: center;
			min-width: 25px;
			min-height: 30px;
			/*flex-basis: 100%;*/
			white-space: nowrap;
		}
		.edit-button > i {
			font-size: 1em;
			padding: 0;
			margin: 0;
		}
		.edit-button > span {
			padding: 0 8px;
		}
		.edit-button:hover {
			background-color: var(--menu-accent);
		}
		.edit-active {
			background-color: var(--main-accent);
			color: white;
		}
		.edit-divide {
			display: inline-block;
			height: 15px;
			width: 7px;
			padding: 0;
		}
		@media only screen and (max-width: 740px) {
			.edit-button {
				font-size: 1.2em;
			}
			.menu-top-half, .menu-bottom-half {
				padding: 3px 2px;
				left: 0;
				right: 0;
				transform: none;
				border-radius: 0;
			}
			.menu-bottom-half {
				position: fixed;
				z-index: 100000;
			}
			.note-wrapper {
				margin-bottom: 100px;
				margin-top: 38px;
			}
		}
	/*
	
	Edit Menu Styles END
	
	*/

	.stealth-input {
		width: 100%;
		padding: 15px;
		background-color: var(--small_element_bg_color );
		border: none;
		border-bottom: 2px solid var(--main-accent);
		font-size: 1.7em;
		color: var(--text_color);
		caret-color: var(--main-accent);
		resize: none;
		overflow: hidden;
		/*margin: 0;*/
		outline: none;
		display: block;

		margin-left: auto;
		margin-right: auto;
		max-width: 1100px;

	}

	/*Settings manager styles */
	.all-settings {
		background: #221f2b;
		z-index: 99;
		flex-grow: 0;
	}
	/*End Settings manager styles */

	/* container styles change based on mobile and number of open screens */
/*	.master-note-edit {
		position: fixed;
		bottom: 0;
		height: 100vh;
		z-index: 1001;
		left: 15%;
		right: 15%;

		overflow-y: scroll;
		overflow-x: hidden;
		scrollbar-width: none;
		scrollbar-color: transparent transparent;
	}*/
	.loading-note {
		position: absolute;
		top: 0;
		width: 100%;
		height: 100%;
		min-height: 300px;
		/*background: var(--small_element_bg_color);*/
		/*opacity: 0.;*/
		z-index: 1;
	}
	.loading-text {
		margin: 0;
	    position: absolute;
	    top: 200px;
	    left: 50%;
	    margin-right: -50%;
	    transform: translate(-50%, -50%);
	}

	/* One note open, in the middle of the screen */
	.side-menu-open {
		left: calc(50% + 10px) !important;
		right: calc(0% + 10px) !important;
	}
	/*weird inbetween size for tables*/
	@media only screen and (max-width: 875px) {

	}
	@media only screen and (max-width: 830px) {
		.shade1, .shade2 {
			right: 150%;
		}
		.edit-divide {
			display: none;
		}
		.edit-button {
			padding: 6px 0px 0;
		}
		.edit-button > span:not(.ui) {
			display: none;
		}
	}



	/* animations START */

		.slide-out-top {
			animation: slide-out-top 0.5s ease;
		}

		@keyframes slide-out-top {
			0% {
				top: 0;
			}
			100% {
				top: -100px;
			}
		}

		.size-down {
			animation: size-down 0.5s ease;
		}

		@keyframes size-down {
			0% {
				top: 0;
			}
			100% {
				top: 150vh;
			}
		}

		.fade-me-out {
			animation: fade-me-out 0.5s ease;
		}

		@keyframes fade-me-out {
			0% {
				opacity: 1;
			}
			100% {
				opacity: 0;
			}
		}

		.slide-out-right {
			animation: slide-out-right 0.5s ease;
		}

		@keyframes slide-out-right {
			0% {
				right: 85%;
			}
			100% {
				right: 150%;
			}
		}

		/* Fade out transition animation */
		.fade-enter {
			/*opacity: 0;*/
		}

		.fade-enter-active {
			/*transition: opacity 0.7s;*/
		}

		.fade-leave {
			/* opacity: 0; */
		}

		.fade-leave-active {
			transition: opacity 0.7s;
			opacity: 0;
		}
	/* animations END */

</style>