<script setup>
	import { onMounted, getCurrentInstance, ref } from 'vue'

	const micThresholdExceeded = defineModel('micThresholdExceeded')
	const timerRunning = defineModel('timerRunning')

	const { proxy } = getCurrentInstance();

	const descriptionInput = ref(null)

	onMounted(()=>{
		window.addEventListener('keydown', (event)=>{
			if(event.key === 'ArrowDown'){
				event.preventDefault()
				proxy.start()
			} else if (event.key === 'ArrowUp'){
				event.preventDefault()
				proxy.stop()
			}
			if(event.ctrlKey === true){
				if(event.key === 'Enter'){ 
					proxy.submit(event)
				} else if(event.key === 'd') {
					descriptionInput.value.focus()
				}
			}
		})
	})
</script>
<script>
	import axios from 'axios';

	import CategoryChooser from './category_chooser.vue'
	import { getHours, getMinutes, createTimeObj, getAccumulatedSeconds, formatSeconds } from '../libs/time.js'
	import {
		copiedSongs,
		currentWorkingCategory,
		currentWorkingInstrument,
		description
	} from '../libs/state.js'

	export default {
		data() {
			return {
				submitting:false,
				startTime:0,
				savedPreviousSeconds:0,
				totalSeconds:0,
				comments:'',
				manualHours:0,
				manualMinutes:0,
				manualSeconds:0,
				analyser:null,
				secondsToSubtract:0,
				micThreshold:-1,
				micLevel:0,
				practice_category_id:0
			}
		},
		emits: ['loggedTime'],
		components: {
			CategoryChooser
		},
		methods: {
			formatSeconds,
			submit(event){
				event.preventDefault();
				if(this.submitting){
					return
				} else {
					this.submitting = true
				}
				const reqBody = {
					description:description.value,
					seconds: this.totalSeconds,
					practice_category_id: currentWorkingCategory.value.id,
				}

				if(copiedSongs.value.length > 0){
					reqBody.songs = copiedSongs.value
				}

				if(this.comments){
					reqBody.comments = this.comments
				}

				axios.post(
					import.meta.env.VITE_PRACTICE_TRACKER_API_URL+'sessions',
					reqBody
				).then(()=>{
					description.value = null;
					copiedSongs.value = []
					this.totalSeconds = 0;
					this.savedPreviousSeconds = 0;
					this.comments = null;
					this.secondsToSubtract = 0;
					this.manualHours = 0
					this.manualMinutes = 0
					this.manualSeconds = 0
					window.localStorage.setItem('lastTotalSeconds', this.totalSeconds);
					this.$emit('loggedTime', reqBody)
					this.submitting = false
				},()=>{
					this.submitting = false
				});

			},
			start(event){
				if(this.timerRunning === false){
					this.startTime = Date.now();
					this.$emit('update:timerRunning', true)
					this.intervalID = setInterval(()=>{

						if(this.micThreshold > -1){

							const array = new Uint8Array(this.analyser.frequencyBinCount);
							this.analyser.getByteFrequencyData(array);
							const arraySum = array.reduce((a, value) => a + value, 0);
							this.micLevel = arraySum / array.length;

							if(this.micLevel < this.micThreshold){
								this.secondsToSubtract++;
							}

						}

						if(this.micLevel >= this.micThreshold){
							this.$emit('update:micThresholdExceeded', true)
						} else {
							this.$emit('update:micThresholdExceeded', false)
						}

						this.totalSeconds = getAccumulatedSeconds(Date.now(), this.startTime) - this.secondsToSubtract + this.savedPreviousSeconds;
						this.setManualTime(this.totalSeconds)
						window.localStorage.setItem('lastTotalSeconds', this.totalSeconds);
					}, 1000);
				}
			},
			setManualTime(seconds){
				const timeObj = createTimeObj(this.totalSeconds)
				this.manualHours = timeObj.hours
				this.manualMinutes = timeObj.minutes
				this.manualSeconds = timeObj.seconds
			},
			updateSavedPreviousSeconds(event){
				this.savedPreviousSeconds = parseInt(event.target.value);
				this.setManualTime(this.totalSeconds)
			},
			stop(event){
				if(this.timerRunning === true){
					this.$emit('update:timerRunning', false)
					this.savedPreviousSeconds += getAccumulatedSeconds(Date.now(), this.startTime);
					clearInterval(this.intervalID);
				}
			},
			reset(event){
				this.savedPreviousSeconds = 0;
				this.totalSeconds = 0;
				this.secondsToSubtract = 0;
				this.manualHours = 0
				this.manualMinutes = 0
				this.manualSeconds = 0
				window.localStorage.setItem('lastTotalSeconds', this.totalSeconds);
			},
			setSecondsManually(){
				this.totalSeconds = this.manualHours*60*60 + this.manualMinutes*60 + this.manualSeconds;
				this.savedPreviousSeconds = this.totalSeconds;
				this.secondsToSubtract = 0;
				window.localStorage.setItem('lastTotalSeconds', this.totalSeconds);
			},
			activateMic(){

				if(this.micThreshold > -1){

					navigator.mediaDevices.getUserMedia({
						audio: true
					}).then((stream) => {

						const audioContext = new AudioContext();
						this.analyser = audioContext.createAnalyser();
						const microphone = audioContext.createMediaStreamSource(stream);
						const scriptProcessor = audioContext.createScriptProcessor(2048, 1, 1);

						this.analyser.smoothingTimeConstant = 0.8;
						this.analyser.fftSize = 1024;

						microphone.connect(this.analyser);
						this.analyser.connect(scriptProcessor);
						scriptProcessor.connect(audioContext.destination);

					})
					.catch((err) => {
						console.error(err);
					});

				}

			},
			confirmClose(event){
				if(this.totalSeconds > 0){
					event.returnValue = "Clear or save your time"
					return false
				}
			},
		},
		mounted() {
			this.practice_category_id = currentWorkingCategory.value.id
			if(window.localStorage.getItem('lastTotalSeconds')){
				this.totalSeconds = parseInt(window.localStorage.getItem('lastTotalSeconds'))
			} else {
				this.totalSeconds = 0
			}
			this.setManualTime(this.totalSeconds)
			this.savedPreviousSeconds = this.totalSeconds
			window.onbeforeunload = this.confirmClose
		},
	}
</script>

<template>
	<h2>Timer</h2>
	<div>
		<em>
			{{formatSeconds(totalSeconds)}}
		</em>
		Mic Threshold (current level: {{Math.round(micLevel)}}):
		<input type="number" @change="activateMic" v-model="micThreshold"/>
		<button :disabled="timerRunning" @click="start">Start</button>
		<button :disabled="!timerRunning" @click="stop">Stop</button>
		<button :disabled="timerRunning || totalSeconds === 0" @click="reset">Reset</button>
	</div>
	<form @submit="submit">
		<label>Description</label>
		<input v-model="description" ref="descriptionInput" type="text" maxlength="128"/>

		<label>Songs</label>
		<ul v-if="copiedSongs.length > 0">
			<li v-for="song in copiedSongs">
				<a v-bind:href="'#/songs/' + song.id">
					{{song.title}}
				</a>
			</li>
		</ul>

		<label>Seconds</label>
		<input @change="updateSavedPreviousSeconds" v-model="totalSeconds" type="number"/>

		<label>Practice Category</label>
		<CategoryChooser />
		<input :disabled="submitting" type="submit"/>

		<label>Comments</label>
		<textarea v-model="comments"/>

		<label>Hours:</label>
		<input type="number" @change="setSecondsManually" v-model="manualHours"/>
		<label>Minutes:</label>
		<input type="number" @change="setSecondsManually" v-model="manualMinutes"/>
		<label>Seconds:</label>
		<input type="number" @change="setSecondsManually" v-model="manualSeconds"/>
	</form>
</template>

<style scoped>
label, [type="submit"] {
	display:block;
}

input[type="number"] {
	width: 5em;
}

button, em, [type="submit"]{
	margin: 1em 0;
	display:block;
	font-size:3em;
	font-style:normal;
	font-weight:bold;
	width:100%;
}
select {
	width: 100%;
}

</style>
