function showFSATeamCountTroll() {

	var fsatctel = document.getElementById('fsateamcounttroll')
	fsatctel.innerHTML = (state.fsaTeamCountTroll + ' teams have already answered this question')

}

function updateFSATeamCountTroll() {

	if (state.fsaTeamCountTroll > (128*Math.random())) {
		showFSATeamCountTroll()
		return
	}

	// `|| state.submitTime` is a workaround for saved Qs that don't have a time set yet
	var time = state.questions[state.currentQuestion].time || state.submitTime
	var timeratio = 1 - (state.submitTimer / time)
	var slowAnswerChance = Math.random()*2*Math.pow(timeratio, 2)
	var quickAnswerChance = (Math.random()+Math.sqrt(69/time))/4
	var chance = Math.round(slowAnswerChance + quickAnswerChance)
	var magnitude = Math.round((Math.random()/2+timeratio)*6)
	var nt = chance * magnitude
	state.fsaTeamCountTroll += nt

	showFSATeamCountTroll()

}

function updateTotalTimer() {

	var timerEls = document.querySelectorAll('.totaltimer')

	for (timerEl of timerEls)
		timerEl.innerHTML = 'Total time: ' + formatTime(state.totalTimer);

	if (!state.waitNextQuestion)
		state.totalTimer++

	localStorage.setItem('state', JSON.stringify(state))

	if (state.style == 'FSA')
		updateFSATeamCountTroll()

}


function startTotalTimer() {

	console.log('Setting totalTimer to ' + state.totalTimer + ' seconds.')

	updateTotalTimer()

	state.totalInterval = setInterval(updateTotalTimer, 1000)

}

function skipWaitNextQuestion(event) {

	if (!event.shiftKey)
		return

	console.log('Skipping/Bypassing wait timer')

	state.submitTimer = 0
	updateSubmitTimer()

}

function updateSubmitInfo() {

	var button = document.getElementById('quizSubmitButton')
	var si = document.getElementById('submitinfo')

	if (getRule('submitTimeout') || state.waitNextQuestion) {
		if (state.submitTimer > 0) {
			si.innerHTML = state.waitNextQuestion ? 'Waiting for next question' : 'Wait to retry'
			button.value = 'Wait ' + formatTime(state.submitTimer)
			button.readOnly = true
			button.addEventListener('click', skipWaitNextQuestion)
			return
		}
	}

	si.innerHTML = ''
	button.readOnly = false
	button.removeEventListener('click', skipWaitNextQuestion)

	if (getRule('questionTimeout')) {
		if (state.submitTimer > 0) {
			if (getRule('allowQOvertime'))
				si.innerHTML = ('Losing bonus points in ' + formatTime(state.submitTimer))
			else
				si.innerHTML = ('Forced hand-in in ' + formatTime(state.submitTimer))
		} else {
			if (getRule('allowQOvertime'))
				document.getElementById('submitinfo').innerHTML = 'Bonus points lost.'
		}
	}

	var lastQuestion = (state.currentQuestion == (state.questions.length - 1))

	button.value = lastQuestion || !getRule('sequential') ? 'Submit Answers' : 'Next Question'

}

function updateSubmitTimer() {

	if (state.submitTimer > 0)
		state.submitTimer -= 1

	if (state.submitTimer == 0) {

		clearInterval(state.submitInterval)

		if (getRule('questionTimeout'))
			if (state.waitNextQuestion || !getRule('allowQOvertime'))
				submitQuiz() // Force next question

	}

	updateSubmitInfo()

}


function startSubmitTimer(time) {

	state.submitTimer = time || state.questions[state.currentQuestion].time || state.submitTime
	if (state.submitTimer == null)
		return

	console.log('Setting submitTimer to ' + state.submitTimer + ' seconds.')

	updateSubmitTimer()

	state.submitInterval = setInterval(updateSubmitTimer, 1000)

}


function updateSequentialQuestion() {

	var questions = document.querySelectorAll('.question')
	for (q of questions)
		q.style.display = null

	updateSubmitInfo()

	if (state.currentQuestion !== null && !state.waitNextQuestion) {
		var q = document.querySelector('#quiz form #question' + state.currentQuestion)
		q.style.display = 'block'
	}

}

function nextQuestion() {

	// Save time taken
	state.questions[state.currentQuestion].timeTaken = state.totalTimer - state.questionStartTotalTimer

	// Last question
	if (state.currentQuestion == (state.questions.length - 1)) {
		state.currentQuestion = null
		updateSequentialQuestion()
		return
	}

	// Waiting for next question
	if (getRule('questionTimeout') && (state.submitTimer > 0)) {
		state.waitNextQuestion = true;
		updateSequentialQuestion() // hide question
		return
	}

	state.waitNextQuestion = false

	if (state.style == 'FSA') {
		state.fsaTeamCountTroll = 0
		showFSATeamCountTroll()
	}

	// Start next question
	state.questionStartTotalTimer = state.totalTimer

	state.currentQuestion++

	updateSequentialQuestion()

	if (getRule('questionTimeout'))
		startSubmitTimer()

}


function renderQuiz() {

	var quizForm = document.querySelector('#quiz form')

	quizForm.className = ''
	if (getRule('sequential'))
		quizForm.classList.add('sequential')

	quizForm.innerHTML = ''

	for (const [i, q] of state.questions.entries()) {

		var html = `<div class="question" id="question${i}">`

		html += `<h3>Question #${i+1}</h3>`
		html += `<h4>${q.question}</h4>`

		if (q.picture)
			html += `<img src="${q.picture}">`

		if (q.type == 'ChooseOne' || q.type == 'ChooseAny') {

			var choices = Array.from(q.choices.entries())
			var shuffled = choices.sort(() => Math.random() - 0.5)

			for ([ci, c] of shuffled)
				html += (q.type == 'ChooseOne')
					? `<label><input type="radio" name="q${i}" value="${ci+1}"> <p>${c}</p></label><br>`
					: `<label><input type="checkbox" name="q${i}" value="${ci+1}"> <p>${c}</p></label><br>`

		} else if (q.type == 'Text') {

			// If choices were given, use them as labels, otherwise use generic label
			for ([ai, a] of q.answers.entries())
				html += `<label>${q.choices[ai] ? q.choices[ai] : 'Answer'}<input type="text" name="q${i}"></label>`

		}

		html += '</div>'

		quizForm.innerHTML += html

	}

}


function startQuiz() {

	state.success = false

	console.log('Starting/Resuming quiz. State:')
	console.log(state)

	renderQuiz()

	changeView('quiz')

	if (getRule('sequential'))
		updateSequentialQuestion()

	if (state.submitTimer > 0)
		startSubmitTimer(state.submitTimer)
	else if (getRule('questionTimeout'))
		startSubmitTimer()
	else
		updateSubmitInfo()

	startTotalTimer()
	state.running = true

	console.log('Quiz started/resumed')

}

function reStartQuiz() {

	console.log('Restarting quiz');

	state.responses					= defaultState.responses
	state.currentQuestion			= defaultState.currentQuestion
	state.waitNextQuestion			= defaultState.waitNextQuestion
	state.success					= defaultState.success
	state.submitTry					= defaultState.submitTry
	state.submitTimer				= defaultState.submitTimer
	state.submitInterval			= defaultState.submitInterval
	state.questionStartTotalTimer	= defaultState.questionStartTotalTimer
	state.totalTimer				= defaultState.totalTimer
	state.totalInterval				= defaultState.totalInterval
	state.fsaTeamCountTroll			= defaultState.fsaTeamCountTroll
	state.resultsShown				= defaultState.resultsShown

	changeView('prescreen')

}


function createQuiz(e) {

	e.preventDefault()

	console.log('Creating new quiz')

	clearState()
	removeLink()

	state.title = document.getElementById('titleField').value
	state.style = document.getElementById('styleField').value

	// After state.style is set
	applyRuleSettingsFromForm()

	if (parseSpreadsheet().success == false) {
		alert('Quiz creation failed.')
		return
	}

	console.log('Spreadsheet parsing successful')

	updateTitles()

	changeView('prescreen')

	console.log('Quiz created:')
	console.log(state)

	return false

}


function endQuiz() {

	console.log('Ending quiz')

	state.running = false

	localStorage.removeItem('state')

	//document.querySelector('#quiz form').innerHTML = ''
	changeView('postscreen')

	if (state.submitInterval)
		clearInterval(state.submitInterval)

	clearInterval(state.totalInterval)

	console.log('Quiz ended')

}

function showQuizResults() {

	var quizForm = document.querySelector('#quiz form')
	quizForm.className = ''

	console.log('Showing quiz results...')

	changeView('quiz')

	// Prevent result metadata being added more than once
	if (state.resultsShown)
		return

	for (var [idx, value] of state.responses.entries()) {

		console.log(idx + ':', value)
		var el = document.getElementById('question' + idx)

		// Mark question correct or incorrect
		el.classList.add(value.correct ? 'correct' : 'incorrect')

		var q = state.questions[idx]

		// traverse correct answers
		if (state.questions[idx].type == 'Text') {
			for (var [i, ans] of q.answers.entries()) {
				var inp = el.querySelectorAll('input')[i]

				if (inp.value == ans)
					inp.classList.add('right')
				else {
					var note = document.createElement('p')
					note.innerHTML = ans
					inp.parentElement.appendChild(note)
				}
			}
		} else {
			for (var ans of q.answers)
				el.querySelector(`input[value="${ans}"]`).classList.add('trueans')
		}

		var meta = document.createElement('div')
		meta.className = 'meta'
		meta.innerHTML = `
			<p><i>Source/Author: ${q.author || '[No source/author provided]'}</i></p>
			<h5>Explanation:</h5>
			<p>${q.explanation || '[No explanation provided]'}</p>`
		el.appendChild(meta)

		var qinfo = (value.correct) ? '✅ Correct' : '❌ Incorrect'
		if (q.timeTaken) {
			qinfo += ('. Time taken: ' + formatTime(q.timeTaken))
			if (value.correct && getRule('allowQOvertime'))
				qinfo += (', Bonus points ' + ((q.timeTaken <= q.time) ? 'received' : 'lost'))
			else if (q.timeTaken >= (q.time - 1) && !getRule('allowQOvertime'))
				qinfo += ', Time ran out'
		}
		el.querySelector('h3').innerHTML += ` &nbsp; <span class="meta">${qinfo}</span>`

	}

	state.resultsShown = true

	document.querySelector('#fsateamcounttroll').innerHTML = ''
	document.querySelector('#submitinfo').innerHTML = ''
	document.querySelector('#quizSubmitButton').value = 'Back'

}


function mergeKeyReducer(acc, entry) {

	if (!acc[entry[0]])
		acc[entry[0]] = {answers: [], correct: false}

	acc[entry[0]].answers.push(entry[1])

	return acc

}


function submitQuiz() {

	// If not running, we're most likely in review mode. Just switch back.
	if (state.running == false) {
		changeView('postscreen')
		return
	}

	if (getRule('sequential')) {

		nextQuestion()

		// Not at the end of the quiz yet
		if (state.currentQuestion !== null)
			return

	}

	console.log('Submitting quiz. State:')
	console.log(state)

	var quizForm = document.querySelector('#quiz form')

	var data = new FormData(quizForm)

	var responses = Array.from(data.entries()).reduce(mergeKeyReducer, {})

	console.log(responses)

	var correct = 0
	state.responses = []

	for (var idx = 0; idx < state.questions.length; idx++) {

		var value = responses['q'+idx] || {answers: [], correct: false}

		console.log(idx + ":", value)

		if (state.questions[idx].type == 'ChooseOne' || state.questions[idx].type == 'ChooseAny') {
			state.questions[idx].answers.sort()
			value.answers.sort()
		}

		var correctAnswer = JSON.stringify(state.questions[idx].answers)
		var givenAnswer = JSON.stringify(value.answers)

		console.log('Comparing: ' + givenAnswer + ' == ' + correctAnswer + '?: ' + (givenAnswer == correctAnswer))

		if (givenAnswer == correctAnswer) {
			value.correct = true
			correct++
		}

		state.responses.push(value)

	}

	console.log(state.responses)

	var text = '' + correct + '/' + state.questions.length + ' questions answered correctly.'

	state.success = (correct == state.questions.length)

	if (!state.success) {
		state.submitTry++

		if (getRule('submitTries') && state.submitTry < state.submitTries) {
			alert(text + `\nThis was try ${state.submitTry}/${state.submitTries}\nClick OK to Try Again`)
			renderQuiz()
			if (getRule('sequential')) {
				state.currentQuestion = 0
				updateSequentialQuestion()
			}

			if (getRule('submitTimeout'))
				startSubmitTimer(state.submitTime)
		} else {
			document.querySelector('#postscreen h1').innerHTML = (text + '<br>Maybe next time :)')
			endQuiz()
		}
	}

	if (state.success) {
		document.querySelector('#postscreen h1').innerHTML = (text + '<br>Yay you did it!')
		endQuiz()
	}

	console.log('Quiz submitted')

}


function abortQuiz() {

	console.log('Aborting quiz')

	if (!confirm('You sure you want to abort this quiz? Your progress will be lost.'))
		return

	document.querySelector('#postscreen h1').innerHTML = `Quiz cancelled.`

	endQuiz()

	console.log('Quiz cancelled')

}


function deleteQuiz() {

	clearState()
	removeLink()
	changeView('spreadsheet')

}


window.onload = async function() {

	var browserWarning = document.getElementById('browserwarning')

	// If arrow functions are supported, it's modern enough :P
	browserWarning.style.display = (() => 'none')()

	var stateString = localStorage.getItem('state')

	var urlId = idFromUrl()
	console.log('URL ID:', urlId)

	if (stateString) {

		console.log('Loading local state')
		state = JSON.parse(stateString)

	}

	// only fetch if it's a different one
	var useUrl = (urlId && urlId != state.id)
	if (useUrl) {

		console.log('Using remote quiz from url')

		var quiz = await fetchQuiz(urlId)

		state.style = quiz.style
		state.title = quiz.title
		state.questions = quiz.questions
		state.submitTries = quiz.submitTries
		state.submitTime = quiz.submitTime
		state.id = urlId

		// Workaround for quizzes that were saved before the fix
		// Where the stored value is null instead of Infinity
		if (state.style == 'FSCzech')
			state.submitTries = Infinity

		changeView('prescreen')

	}

	updateTitles()
	var meme = memes[Math.floor(Math.random()*memes.length)]
	document.getElementById('meme').innerHTML = meme

	if (stateString && !useUrl)
		if (state.running)
			startQuiz()
		else
			changeView('prescreen')

	if (!stateString && !useUrl)
		changeView('spreadsheet')

	console.log('onload complete')

}