<template>
	<div class="ui basic segment no-fluf-segment">
		
		<div class="ui grid" :class="{ 'mush-it-up':showOneColumn() }" ref="content">

			<!-- Note filter options  -->
			<div class="row">
				
				<div 
					:class="{ 'sixteen wide column':showOneColumn(), 'eight wide column':!showOneColumn() }"
				>
					<div class="ui form">
						<div class="fields">
							<div class="ten wide field">
								<input v-model="searchTerm" @keyup="searchKeyUp" @:keyup.enter="search" placeholder="Search Notes" />
							</div>
							<div class="six wide field">
								<span class="ui fluid green button" 
									v-if="showClear"
									@click="reset">
									<i class="undo icon"></i>Reset Filters
								</span>
							</div>
						</div>
					</div>
				</div>
				<div 
					:class="{ 'sixteen wide column':showOneColumn(), 'eight wide column':!showOneColumn() }"
				>
					<h2 class="ui right floated">
						<fast-filters />
					</h2>
				</div>
			</div>

			<div v-if="commonTags.length > 0" class="sixteen wide column">
				<span v-for="tag in commonTags" @click="toggleTagFilter(tag.id)">
					<span class="ui clickable basic label" :class="{ 'green':(searchTags.includes(tag.id)) }">
					{{ucWords(tag.text)}} <span class="detail">{{tag.usages}}</span>
					</span>
				</span>
			</div>

			<h2 v-if="fastFilters['withLinks'] == 1">Only showing notes containing Links</h2>
			<h2 v-if="fastFilters['withTags'] == 1">Only showing notse with Tags</h2>
			<h2 v-if="fastFilters['onlyArchived'] == 1">Only showing Archived notes.</h2>

			<!-- Note title card display  -->
			<div class="sixteen wide column">
				<h3 v-if="searchTerm.length > 0 && notes.length == 0">No notes found. Check your spelling, try completing the word or using a different phrase.</h3>

				<h3 v-if="searchTerm.length == 0 && notes.length == 0">Create your first note. Click the "New Note" button.</h3>

				<div v-if="working">
					<div class="ui active inline loader"></div> Working...
				</div>

				<!-- Go to one wide column, do not do this on mobile interface -->
				<div v-if="notes !== null && notes.length > 0" 
					:class="{'one-column':( 
						(activeNoteId1 != null || activeNoteId2 != null) &&
						!$store.getters.getIsUserOnMobile
					)}">

					<!-- pinned notes -->
					<div v-if="containsPinnednotes > 0" class="note-card-section">
						<h4><i class="green pin icon"></i>Pinned <span v-if="!working">({{containsPinnednotes}})</span></h4>
						<div class="note-card-display-area">
							<note-title-display-card 
								v-for="note in notes"
								v-if="note.pinned"
								:onClick="openNote"
								:data="note"
								:currently-open="(activeNoteId1 == note.id || activeNoteId2 == note.id)"
								:key="note.id + note.color + note.note_highlights.length + note.attachment_highlights.length + ' -' + note.tag_highlights.length + '-' +note.title.length + '-' +note.subtext.length"
							/>
						</div>
					</div>

					<!-- normal notes  -->
					<div v-if="containsNormalNotes > 0" class="note-card-section">
						<h4>Notes <span v-if="!working">({{containsNormalNotes}})</span></h4>
						<div class="note-card-display-area">
							<note-title-display-card 
								v-for="note in notes"
								v-if="note.note_highlights && !note.pinned"
								:onClick="openNote"
								:data="note"
								:currently-open="(activeNoteId1 == note.id || activeNoteId2 == note.id)"
								:key="note.id + note.color + note.note_highlights.length + note.attachment_highlights.length + ' -' + note.tag_highlights.length + '-' +note.title.length + '-' +note.subtext.length"
							/>
						</div>
					</div>

					<!-- found in text  -->
					<div v-if="containsTextResults" class="note-card-section">
						<h4><i class="green paragraph icon"></i> Found in Text ({{containsTextResults}})</h4>
						<div class="note-card-display-area">
							<note-title-display-card 
								v-for="note in notes"
								v-if="note.note_highlights && note.note_highlights.length"
								:textResults="true"
								:onClick="openNote"
								:data="note"
								:currently-open="(activeNoteId1 == note.id || activeNoteId2 == note.id)"
								:key="note.id + note.color + note.note_highlights.length + note.attachment_highlights.length + ' -' + note.tag_highlights.length + '-' +note.title.length + '-' +note.subtext.length"
							/>
						</div>
					</div>
				</div>

			</div>

		</div>

		
		<input-notes v-if="activeNoteId1 != null" :noteid="activeNoteId1" :position="activeNote1Position" />
		<input-notes v-if="activeNoteId2 != null" :noteid="activeNoteId2" :position="activeNote2Position" />

		<div v-if="openAttachmentEdit">
			<edit-attachment :note-id="editAttchmentId" :key="editAttchmentId" />
		</div>

	</div>
</template>

<script>
	
	import axios from 'axios'

	export default {
	name: 'SearchBar',
		components: {
			'input-notes': require('@/components/NoteInputPanel.vue').default,
			'note-title-display-card': require('@/components/NoteTitleDisplayCard.vue').default,
			'fast-filters': require('@/components/FastFilters.vue').default,
			'edit-attachment': require('@/components/AttachmentEditor.vue').default,
		},
		data () {
			return {
				initComponent: true,
				commonTags: [],
				searchTerm: '',
				searchTags: [],
				notes: [],
				highlights: [],
				searchDebounce: null,
				fastFilters: {},
				working: false,
				//Load up notes in batches
				firstLoadBatchSize: 30, //First set of rapidly loaded notes
				batchSize: 100, //Size of batch loaded when user scrolls through current batch
				batchOffset: 0, //Tracks the current batch that has been loaded
				loadingBatchTimeout: null, //Limit how quickly batches can be loaded
				loadingInProgress: false,

				//Clear button is not visible 
				showClear: false,
				initialPostData: null,
				currentPostData: null,

				containsNormalNotes: 0,
				containsPinnednotes: 0,
				containsTextResults: 0,
				containsTagResults: 0,
				containsAttachmentResults: 0,

				//Currently open notes in app
				activeNoteId1: null,
				activeNoteId2: null,

				//Position determines how note is Positioned
				activeNote1Position: 0,
				activeNote2Position: 0,

				//Attchment to edit. Only 1 for now
				openAttachmentEdit: false,
				editAttchmentId: null,
			}
		},
		beforeMount(){

			this.$parent.loginGateway()

			this.$bus.$on('open_edit_attachment', noteId => {
				this.openAttachmentEdit = true
				this.editAttchmentId = noteId
			})
			this.$bus.$on('close_edit_attachment', noteId => {
				this.openAttachmentEdit = false
				this.editAttchmentId = null
			})

			this.$bus.$on('close_active_note', position => {
				this.closeNote(position)
			})
			this.$bus.$on('note_deleted', () => {
				this.search()
			})
			this.$bus.$on('update_fast_filters', newFilter => {
				this.fastFilters = newFilter
				this.search(true, this.batchSize, false)
			})

			//New note button pushes open note event
			this.$bus.$on('open_note', noteId => {
				this.openNote(noteId)
			})

			//Mount notes on load if note ID is set
			if(this.$route.params && this.$route.params.id){
				const id = this.$route.params.id
				this.openNote(id)
			}
			window.addEventListener('scroll', this.onScroll)

			//Load tinymce into the page only do it once
			if(document.querySelectorAll('[data-mceload]').length == 0){
				let tinyMceIncluder = document.createElement('script')
				tinyMceIncluder.setAttribute('src', '/api/static/assets/tinymce/tinymce.min.js')
				tinyMceIncluder.setAttribute('data-mceload','loaded')
				document.head.appendChild(tinyMceIncluder)
			}

		},
		beforeDestroy(){
			window.removeEventListener('scroll', this.onScroll)
		},
		mounted() {

			//Load a super fast batch
			this.search(true, this.firstLoadBatchSize, 0)
			.then( () => {
				//Load a larger batch once first batch has loaded
				this.search(false, this.batchSize, true).then( () => {

				})
			})

		},
		methods: {
			showOneColumn(){
				//If note 1 or 2 is open, show one column. Or if the user is on mobile
				return (this.activeNoteId1 != null || this.activeNoteId2 != null) &&
						!this.$store.getters.getIsUserOnMobile
			},
			openNote(id){

				//Do not open same note twice
				if(this.activeNoteId1 == id || this.activeNoteId2 == id){
					return;
				}

				//1 note open
				if(this.activeNoteId1 == null && this.activeNoteId2 == null){
					this.activeNoteId1 = id
					this.activeNote1Position = 0 //Middel of page
					this.$router.push('/notes/open/'+this.activeNoteId1)
					return
				}
				//2 notes open
				if(this.activeNoteId1 != null && this.activeNoteId2 == null){
					this.activeNoteId2 = id
					this.activeNote1Position = 1 //Right side of page
					this.activeNote2Position = 2 //Left side of page
					return
				}
				//2 notes open
				if(this.activeNoteId2 != null && this.activeNoteId1 == null){
					this.activeNoteId1 = id
					this.activeNote1Position = 2 //Right side of page
					this.activeNote2Position = 1 //Left side of page
					return
				}
			},
			closeNote(position){
				//One note open, close that note
				if(position == 0){
					this.activeNoteId1 = null
					this.activeNoteId2 = null
				}
				//Right note closed, thats 1
				if(position == 1){
					this.activeNoteId1 = null
				}
				if(position == 2){
					this.activeNoteId2 = null
				}

				this.$router.push('/notes')

				this.activeNote1Position = 0
				this.activeNote2Position = 0

				this.search(false)
			},
			toggleTagFilter(tagId){

				if(this.searchTags.includes(tagId)){
					this.searchTags.splice( this.searchTags.indexOf(tagId) , 1);
				} else {
					this.searchTags.push(tagId)
				}

				this.search()
			},
			onScroll(e){

				clearTimeout(this.loadingBatchTimeout)
				this.loadingBatchTimeout = setTimeout(() => {

					//Distance to bottom of page
					const bottomOfWindow = 
					Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop) 
					+ window.innerHeight

					//height of page
					const offsetHeight = this.$refs.content.clientHeight

					//Determine percentage down the page
					const percentageDown = Math.round( (bottomOfWindow/offsetHeight)*100 )
					
					// console.log( percentageDown + '%' )

					//If greater than 80 of the way down the page, load the next batch
					if(percentageDown >= 80){

						console.log('loading batch')
						this.search(false, this.batchSize, true)
					}

				}, 50)

				
				return
			},
			search(showLoading = true, notesInNextLoad = null, mergeExisting = false){
				return new Promise((resolve, reject) => {

					if(this.loadingInProgress){
						return resolve()
					}

					//Remove all filter limits
					delete this.fastFilters.limitSize
					delete this.fastFilters.limitOffset

					let postData = {
						searchQuery: this.searchTerm,
						searchTags: this.searchTags,
						fastFilters: this.fastFilters,
					}

					if(showLoading){
						this.working = true
					}

					//Save initial post data on first load
					if(this.initialPostData == null){
						this.initialPostData = JSON.stringify(postData)
					}
					//If post data is not the same as initial, show clear button
					if(JSON.stringify(postData) != this.initialPostData){
						this.showClear = true
					}

					if(notesInNextLoad && notesInNextLoad > 0){
						//Create limit based off of the number of notes already loaded
						postData.fastFilters.limitSize = notesInNextLoad
						postData.fastFilters.limitOffset = this.batchOffset
					}

					//Perform search - or die
					this.loadingInProgress = true
					axios.post('/api/note/search', postData).
					then(response => {

						if(!mergeExisting){
							this.containsNormalNotes = 0
							this.containsPinnednotes = 0
							this.containsTextResults = 0
							this.batchOffset = 0 // Reset batch offset if we are not merging note batches
							
							this.commonTags = []
							this.notes = []
						}

						//Save the number of notes just loaded
						this.batchOffset += response.data.notes.length

						//Mush the two new sets of data together
						this.commonTags = this.commonTags.concat(response.data.tags)
						this.notes = this.notes.concat(response.data.notes)


						//Go through each note and see which section to display
						response.data.notes.forEach(note => {

							if(note.note_highlights.length > 0){
								this.containsTextResults++
								return
							}

							if(note.pinned == 1){
								this.containsPinnednotes++
								return
							}

							this.containsNormalNotes++
						})
						
						this.working = false
						this.loadingInProgress = false

						return resolve(true)
					})
				})
			},
			searchKeyUp(){
				let vm = this
				clearTimeout(vm.searchDebounce)
				vm.searchDebounce = setTimeout(() => {
					vm.search()
				}, 500)
			},
			ucWords(str){
				return (str + '')
				.replace(/^(.)|\s+(.)/g, function ($1) {
					return $1.toUpperCase()
				})
			},
			reset(){
				this.showClear = false
				this.searchTerm = ''
				this.searchTags = []
				this.fastFilters = {}
				this.$bus.$emit('reset_fast_filters')
				this.search(true, this.firstLoadBatchSize, 0)
			}
		}
	}
</script>
<style type="text/css" scoped>
	.mush-it-up {
		width: calc(50% - 130px);
	}
	.detail {
		float: right;
	}
	.note-card-display-area {
		display: flex;
		flex-wrap: wrap;
	}
	.display-area-title {
		width: 100%;
		display: inline-block;
	}
	.note-card-section {
		/*padding-bottom: 15px;*/
	}
	.note-card-section + .note-card-section {
		padding: 15px 0 0;
	}
</style>