<template>
	<!-- change class to .master-note-edit to have it popup on the screen  -->
	<div 
		id="InputNotes" 
		class="master-note-edit" 
		@keyup.esc="close" 
		:class="[{'size-down':(sizeDown == true)},  'position-'+position ]" 
		:style="{ 'background-color':styleObject['noteBackground'], 'color':styleObject['noteText']}"
	>

		<!-- Loading indicator  -->
		<div v-if="loading" class="loading-note">
			<div class="ui active dimmer">
				<div class="ui text loader">{{loadingMessage}}</div>
			</div>
		</div>

		<!-- Menu  -->
		<div class="note-top-menu">
			<div @click="close" class="ui basic icon button" data-tooltip="Close" data-position="right center" data-inverted="">
				<i class="close icon"></i>
			</div>

			<div @click="onTogglePinned" class="ui basic icon button" data-tooltip="Pin to Top" data-position="right center" data-inverted="">
				<i class="pin icon" :class="{green:(pinned == 1)}"></i> {{(pinned == 1)?'Pinned':''}}
			</div>
			<div @click="onToggleArchived" class="ui basic icon button" data-tooltip="Hide on main" data-position="right center" data-inverted="">
				<i class="archive icon" :class="{green:(archived == 1)}"></i> {{(archived == 1)?'Archived':''}}
			</div>

			<!-- <file-upload-button :noteId="noteid" /> -->

			<span class="relative" v-on:click="showColorPicker">
				<span class="ui basic icon button">
					<i class="paint brush icon"></i>
				</span>
			</span>

			<div v-if="attachmentCount > 0" class="ui basic icon button" v-on:click="openEditAttachment" data-tooltip="View Links/Images" data-position="right center" data-inverted="">
				<i class="folder icon"></i>
			</div>
			
			<span class="note-status-indicator">{{statusText}}</span>
		</div>



		<textarea :id="noteid+'-tinymce-editor'">{{noteText}}</textarea>

		<note-tag-edit v-if="!$store.getters.getIsUserOnMobile" :noteId="noteid" :key="'tags-for-note-'+noteid"/>

		<color-picker 
			v-if="colorPickerVisible" 
			:location="colorPickerLocation" 
			@changeColor="onChangeColor" 
			:style-object="styleObject" 
		/>



	</div>
</template>

<script>

	import axios from 'axios'
	
	export default {
	name: 'InputNotes',
		props: [ 'noteid', 'position' ],
		components:{
			'note-tag-edit': require('@/components/NoteTagEdit.vue').default,
			'color-picker': require('@/components/ColorPicker.vue').default,
			'file-upload-button': require('@/components/FileUploadButton.vue').default,
		},
		data(){
			return {
				loading: true,
				loadingMessage: 'Loading Note',
				currentNoteId: 0,
				noteText: '',
				statusText: 'Saved',
				lastNoteHash: null,
				saveDebounce: null, //Prevent save from being called numerous times quickly
				updated: 'Never',
				editDebounce: null,
				keyPressesCounter: 0, //Determen 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
				colorPickerVisible: false, 
				colorPickerLocation: null,

                tinymce: null, //Initialized editor instance
			}
		},
		watch: {
			noteid:function(newVal, oldVal){

				if(newVal == this.currentNoteId){
					return
				}

				if(newVal == oldVal){
					return
				}
				
				this.currentNoteId = newVal
				this.loadNote(this.currentNoteId)
				
			}
		},
		beforeMount(){

		},
		beforeDestroy(){
			this.$bus.$off('toggle_night_mode', this.listener)
			//Trash editor instance on close
			this.tinymce.remove()
			
		},
		mounted: function() {

			//Change TinyMce styles on nightmored change
			this.$bus.$on('toggle_night_mode', this.setEditorTextColor )

			this.$nextTick(() => {
				this.loadNote(this.noteid)
			})
		},
		methods: {
			initTinyMce(){

				// image_list: [
				// {title: 'My image 1', value: 'https://www.tinymce.com/my1.gif'},
				// {title: 'My image 2', value: 'http://www.moxiecode.com/my2.gif'}
				// ]

				//Tweak doc height for mobile
				let docHeight = 'calc(100vh - 90px)'
				if(this.$store.getters.getIsUserOnMobile){
					docHeight = 'calc(100vh - 37px)'
				}

				//setup skin as dark if night mode is enabled
				let skin = 'oxide'
				if(this.$store.getters.getIsNightMode){
					skin = 'oxide-dark'
				}

				const editorId = '#'+this.noteid+'-tinymce-editor'

				//Globally defined included in index HTML
				tinymce.init({
					selector: editorId,
					toolbar: 'forecolor backcolor styleselect | bold italic underline | link image | code | undo redo | bullist numlist | outdent indent table, hr, searchreplace | removeformat',
					plugins: 'paste, link, code, lists, table, hr, searchreplace, image',
					browser_spellcheck: true,
					menubar: false,
					branding: false,
					statusbar: false,
					height: docHeight,
					skin: skin,
					contextmenu: false,
					init_instance_callback: this.editorInitCallback,
					imagetools_toolbar: "imageoptions",
				})
			},
			editorInitCallback(editor){

				this.loading = false //Turn off loading screed when editor is loaded
				this.tinymce = editor

				this.setEditorTextColor()

				editor
					.on('Change', this.onKeyup )
					.on('keyup',  this.onKeyup )
					.on('blur',   this.save    )

			},
			setEditorTextColor(){
				//Only Set editor text color, background is transparent and set on parent element

				//There may be scenarios where editor has not been set up
				if(this.tinymce){
					//Set editor color to color from app, change with night mode
					this.tinymce.getBody().style.color = getComputedStyle(document.documentElement)
	    				.getPropertyValue('--text_color');

	    			//Overwrite set color if theme is set for note.
					if(this.styleObject && this.styleObject.noteText){
						this.tinymce.getBody().style.color = this.styleObject.noteText
					}
				}

				
			},
			getText(){
				//Return text from tinyMce Editor
				return this.tinymce.getContent()
			},
			showColorPicker(event){
				this.colorPickerVisible = !this.colorPickerVisible
				this.colorPickerLocation = {'x':event.clientX, 'y':event.clientY}
			},
			openEditAttachment(){
				// this.$bus.$emit('open_edit_attachment', this.currentNoteId)
				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.setEditorTextColor()

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

				let vm = this

				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 = doing[Math.floor(Math.random() * doing.length)]
				let p2 = thing[Math.floor(Math.random() * thing.length)]
				vm.loadingMessage = p1 + ' ' + p2
				
				//Component is activated with NoteId in place, lookup text with associated ID
				if(this.$store.getters.getLoggedIn){
					axios.post('/api/note/get', {'noteId': noteId})
					.then(response => {

						//Set up local data
						vm.currentNoteId = noteId
						vm.noteText = response.data.text
						vm.updated = response.data.updated
						vm.lastNoteHash = vm.hashString(response.data.text)
						if(response.data.color){
							vm.styleObject = JSON.parse(response.data.color) //Load styles json from DB
						}
						
						if(response.data.pinned != null){
							vm.pinned = response.data.pinned
						}
						vm.archived = response.data.archived
						vm.attachmentCount = response.data.attachment_count

						vm.$nextTick(() => {
							this.initTinyMce()
						})

					})
				} else {
					console.log('Could not fetch note')
				}
			},
			onKeyup(){

				this.statusText = 'Modified'

				//Each note, save after 5 seconds, focus lost or 30 characters typed.
				clearTimeout(this.editDebounce)
				this.editDebounce = setTimeout(() => {
					this.save()
				}, 5000)

				//Save after 30 keystrokes
				this.keyPressesCounter = (this.keyPressesCounter + 1)
				if(this.keyPressesCounter > 30){
					this.keyPressesCounter = 0
					this.save()
				}
			},
			save(){
				return new Promise((resolve, reject) => {
					//Clear other debounced events to prevent double calling of save
					clearTimeout(this.editDebounce)

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

					//If user accidentally clears note, it won't delete it
					if(currentNoteText == ''){
						this.statusText = 'Empty'
						console.log('Prevented from saving empty note.')
						return resolve(true)
					}
					
					const postData = {
						'noteId':this.currentNoteId,
						'text': currentNoteText,
						'color': JSON.stringify(this.styleObject), //Save little json color object
						'pinned': this.pinned,
						'archived':this.archived,
					}

					let vm = this
					//Debounce save to prevent spamming
					// clearTimeout(this.saveDebounce)
					// this.saveDebounce = setTimeout(() => {
						//Only notify user if saving - may help with debugging in the future
						vm.statusText = 'Saving'
						axios.post('/api/note/update', postData).then( response => {
							vm.statusText = 'Saved'
							vm.updated = Math.round((+new Date)/1000)

							//Update last saved note hash
							vm.lastNoteHash = vm.hashString( currentNoteText )
							return resolve(true)
						})
					// }, 300)
				})
				
			},
			hashString(text){

				var hash = 0;
				if (text.length == 0) {
					return hash;
				}

				//Simplified for speed
				return text.length

				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;
			},
			close(){

				// this.loading = true
				// this.loadingMessage = 'Save and Close'

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

					this.sizeDown = true
					//This timeout allows animation to play before closing 
					setTimeout(() => {
						this.$bus.$emit('close_active_note', this.position)
						return
					}, 300)
				})
				
			}
		}
	}
</script>

<style type="text/css" scoped>

	.note-top-menu {
		width: 100%;
		display: inline-block;
		height: 37px;
		border-left: 3px solid var(--border_color);
	}
	.note-top-menu .ui.basic.button {
		border-radius: 0;
		border: none;
		border-right: 1px solid var(--border_color);
		margin: 0px -2px;
		padding-left: 15px;
		padding-right: 15px;
	}

	/* container styles change based on mobile and number of open screens */
	.master-note-edit {
		position: fixed;
		bottom: 0;
		background: var(--background_color);
		/*color: var(--text_color);*/
		height: 100vh;
		box-shadow: 0px 0px 5px 2px rgba(140,140,140,1);
		z-index: 1001;
		/*overflow-x: scroll;*/
	}
	.loading-note {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
	}
	/* One note open, in the middle of the screen */
	.master-note-edit.position-0 {
		left: 50%;
		right: 0;
	}
	@media only screen and (max-width: 740px) {
		.master-note-edit.position-0 {
			left: 0;
			right: 0;
			top: 0;
			bottom: 0;
		}
	}

	/* Two Notes Open, each takes up 50% of the space */
	.master-note-edit.position-1 {
		left: 50%;
		right: 0%;
	}
	.master-note-edit.position-2 {
		left: 0%;
		right: 50%;
	}

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

	@keyframes size-down {
		0% {
			/*opacity: 1;*/
			/*top: 0;*/
			top: 0;
		}
		100% {
			/*opacity: 0;*/
			/*top: 30vh;*/
			top: 150vh;
		}
	}

</style>