"use strict";

$(function() {
	
	Notiflix.Loading.dots('Loading...');
	
	let exam = (new function() {
		
		let self = this;
		
		this.template = `
		
			<div data-template class='px-2 px-sm-4'>
						
				<div class='border p-3 row rounded-2'>
					<div class='col-md-9'>
						<h5>
							<span data-part='subject'>%{Subject}</span> : 
							Question <span data-part='position'>%{Q-range}</span> of <span data-part='max'>%{Q-max}</span> 
						</h5>
					</div>
					<div class='text-end text-nowrap'>
						<span data-part='mark'>%{Mark}</span> Mark(s) <i class='far fa-star text-warning'></i>
					</div>
				</div>
				
				<div class='py-3 mb-3 fs-1_1rem'>
					<div data-part='question'>%{Question}</div>
					<div data-part='image'></div>
				</div>
				
				<div class='mb-3 fw-semibold mb-4'>
					<div class='form-check break' data-part='option1'>
						<input type='radio' class='form-check-input' name='option' id='option-1' data-click='option' required>
						<label class='form-check-label' for='option-1'>%{Option1}</label>
					</div>
					<div class='form-check break' data-part='option2'>
						<input type='radio' class='form-check-input' name='option' id='option-2' data-click='option' required>
						<label class='form-check-label' for='option-2'>%{Option2}</label>
					</div>
					<div class='form-check break' data-part='option3'>
						<input type='radio' class='form-check-input' name='option' id='option-3' data-click='option' required>
						<label class='form-check-label' for='option-3'>%{Option3}</label>
					</div>
					<div class='form-check break' data-part='option4'>
						<input type='radio' class='form-check-input' name='option' id='option-4' data-click='option' required>
						<label class='form-check-label' for='option-4'>%{Option4}</label>
					</div>
				</div>
				
				<div class='row row-cols-2 justify-content-between'>
					<div class='col me-auto mb-2' data-part='prev'>
						<button class='btn btn-secondary' data-click>
							<i class='fas fa-angle-double-left me-1'></i> Previous 
						</button>
					</div>
					<div class='col ms-auto text-end' data-part='next'>
						<button class='btn btn-success' data-click>
							Next <i class='fas fa-angle-double-right ms-1'></i>
						</button>
					</div>
					<div class='col-12 mx-auto' data-part='submit'>
						<button class='btn btn-primary w-100' data-click>
							Submit
						</button>
					</div>
				</div>
				
			</div>
			
		`;
		
		this.container = $("#questions").get(0);
		
		let exam;
		let subjectList = [];
		let time, interval;
		let answers = {};
		
		let info = {
			subjectIndex: 0,
			subjectName: '',
			questionList: [],
			questionRange: 0,
			questionIndex: 0,
			question: {}
		};
		
		this.display =  function( subjectIndex, questionIndex ) {
			info.subjectIndex = subjectIndex;
			info.subjectName = subjectList[ info.subjectIndex ];
			info.questionList = exam[ info.subjectName ];
			info.questionRange = info.questionList.length;
			info.questionIndex = questionIndex;
			info.question = info.questionList[ info.questionIndex ];
			this.useTemplate();
		}
		
		this.useTemplate = function() {
			
			if( !info.question ) return;
			
			$(this.container).html( this.template );
			
			$(this.container).find('[data-part]').each(function() {
				
				switch( this.dataset.part ) {
					
					case 'subject':
						return $(this).html( info.subjectName );
						
					case 'position':
						return $(this).html( info.questionIndex + 1 );
						
					case 'max':
						return $(this).html( info.questionRange );
						
					case 'mark':
						return $(this).html( info.question.points );
						
					case 'question':
						return $(this).html( info.question.question );
						
					case 'image':
						if( info.question.image && info.question.image.trim() != '' ) {
							let image = document.createElement('img');
							image.setAttribute('class', 'img-fluid shadow-sm');
							image.setAttribute('src', info.question.image);
							this.appendChild(image);
						};
						return;
						
					case 'prev':
						if( self.isFirstQuestion() ) this.parentElement.removeChild( this );
						return;
						
					case 'next':
						if( self.isLastQuestion() ) this.parentElement.removeChild( this );
						return;
						
					case 'submit':
						if( !self.isLastQuestion() ) this.parentElement.removeChild( this );
						break;
					
				};
				
				let match = this.dataset.part.match(/option(\d)/i);
				
				if( match ) {
					let index = Number(match[1]);
					let option = info.question[ `option${index}` ].trim();
					if( option == '' ) this.parentElement.removeChild( this );
					else {
						$(this).find('label').html( option );
						let input = $(this).find('input').val( index );
						if( answers[ info.question.id ] && answers[ info.question.id ]['answer'] != undefined ) {
							var checked = ( answers[ info.question.id ]['answer'] == index );
						} else {
							var checked = ( parseInt( info.question.selected ) == index );
						};
						input.prop('checked', checked );
					}
				}
				
			});
			
			if( answers[ info.question.id ] == undefined ) $('#frame').get(0).scrollIntoView();
			
		}
		
		this.isFirstQuestion = function() {
			return ( !info.subjectIndex && !info.questionIndex );
		}
		
		this.isLastQuestion = function() {
			// if it's last subject;
			if( info.subjectIndex == (subjectList.length - 1) ) {
				// and it's last question;
				if( info.questionIndex == (info.questionList.length - 1) ) return true;
			};
			return false;
		};
		
		this.startTimer = function() {
			let stamp = 0;
			interval = setInterval(function() {
				for( let x in time ) time[x] = parseInt(time[x]);
				time.second--;
				if( time.second < 0 ) {
					time.minute--;
					time.second = 59;
					if( time.minute < 0 ) {
						time.hour--;
						time.minute = 59;
						if( time.hour < 0 ) {
							time.second = time.minute = time.hour = 0;
							clearInterval( interval );
							self.sendSolution();
							bootbox.alert({
								centerVertical: true,
								size: 'small',
								className: 'text-center',
								message: 'Time Up',
								closeButton: false,
								callback: function() {
									self.submit();
								}
							});
							setTimeout(function() {
								self.submit();
							}, 4000);
						}
					}
				};
				for(let x in time) {
					let value = time[x];
					if( value.toString().length < 2 ) time[x] = '0' + value;
					$(`[data-timer='${x}']`).text( time[x] );
				};
				stamp++;
				if( (stamp / 60) > 0.6 ) {
					stamp = 0;
					self.sendSolution();
				};
			}, 1000);
		}
		
		this.sendSolution = function() {
			self.markAnswer( null );
			$.ajax({
				url: uss.QURL + '/anspire.php',
				method: 'POST',
				data: answers
			});
		}
		
		this.markAnswer = function( selected ) {
			let key = info.question.id;
			if( selected === null ) {
				if( answers[key] != undefined ) return;
			};
			answers[key] = {
				answer: selected,
				epoch: time
			};
		}
		
		this.row = `
			<tr data-row>
				<td></td>
				<td></td>
			</tr>
		`;
		
		this.cease = false;
		
		this.submit = function( el ) {
			if( this.cease ) return;
			this.cease = true;
			Notiflix.Loading.hourglass( 'Please Wait!' );
			self.sendSolution();
			$.ajax({
				url: uss.QURL + '/submit.php',
				method: 'post',
				data: {},
				success: function(response) {
					Notiflix.Loading.remove();
					let result = JSON.parse(response);
					if( !el ) {
						setTimeout(function() {
							Notiflix.Loading.dots( "LOADING RESULTS!" );
							setTimeout(function() {
								window.location.reload();
							}, 4000);
						}, 500);
					} else {
						let data = result.results;
						for( let x in data ) {
							let points = data[x].points;
							let subject = data[x].subject;
							let tr = $(self.row);
							tr.find('td').each(function(i, td) {
								let value = !i ? subject : points;
								$(td).text( value );
							});
							el.appendChild( tr.get(0) );
						};
						$("[data-score]").text( result.score );
						if( result.grade ) {
							$("[data-grade]").text( result.grade.name );
							let percent = result.grade.percent, className;
							if( percent > 80 ) className = 'text-success';
							else if( percent > 50 ) className = 'text-primary';
							else if( percent > 30 ) className = 'text-warning';
							else className = 'text-danger';
							$("[data-percent]").addClass( className );
							$("[data-percent]").html( result.grade.percent + '%' );
						}
					}
				}
			});
		}
		
		this.init = function( result ) {
			
			exam = result.questions;
			time = result.time;
			
			$('#questions').click(function(e) {
				
				if( $(e.target).attr('id') == 'start' ) {
					
					for(let x in exam) subjectList.push( x );
					
					Notiflix.Loading.hourglass( 'Preparing Exam Questions' );
					
					setTimeout(function() {
						Notiflix.Loading.remove();
						self.display(0,0);
						self.startTimer();
					}, 3000);
					
				} else {
					
					let el = e.target;
					while( el && !el.hasAttribute('data-click') ) el = el.parentElement;
					if( !el ) return;
					
					let value = el.parentElement.dataset.part.trim();
					
					// get question positions;
					let questionIndex = info.questionIndex;
					let subjectIndex = info.subjectIndex;
					
					if( value == 'next' ) {
						
						self.markAnswer( null );
						
						// if it is last question of the subject
						if( (info.questionRange - 1) === questionIndex ) {
							subjectIndex++;
							questionIndex = 0;
						} else questionIndex++;
						
						self.display( subjectIndex, questionIndex );
						
					} else if( value == 'prev' ) {
						
						questionIndex--;
						
						if( questionIndex < 0 ) {
							subjectIndex--;
							let subjectName = subjectList[ subjectIndex ];
							questionIndex = ( exam[ subjectName ].length - 1 );
						};
						
						self.display( subjectIndex, questionIndex );
						
					} else if( value == 'submit' ) {
						
						bootbox.confirm({
							closeButton: false,
							message: "Are you sure you are ready to submit your answers? <br> You will not be able to change any option after submittion",
							centerVertical: true,
							className: 'text-center',
							callback: function(yes) {
								if( !yes ) return;
								self.submit();
							}
						});
						
					} else {
						
						let match = value.match(/option(\d)/i);
						
						if( match ) {
							// selected;
							let selected = Number(match[1]);
							self.markAnswer( selected );
						};
						
					};
					
				};
				
			});
			
			$('[data-timer]').each(function() {
				let key = this.dataset.timer;
				this.innerText = time[ key ];
			});
			
		}
		
	});
	
	
	// If no start button! Exit;
	
	if( !$('#start').length ) {
		if( $("#result").length ) {
			let tbody = $("#result [data-tbody]").get(0);
			exam.submit(tbody);
		};
		return Notiflix.Loading.remove();
	};
	
	$.ajax({
		url: uss.QURL + "/questions.php",
		method: 'POST', 
		success: function(response) {
			Notiflix.Loading.remove();
			try {
				let result = JSON.parse(response);
				result.data.questions = JSON.parse( atob(result.data.questions) );
				exam.init( result.data );
			} catch( e ) {
				console.log( e );
			}
		}, 
		error: function() {
			Notiflix.Loading.remove();
			bootbox.confirm({
				size: 'small',
				verticalCenter: true,
				callback: function(yes) {
					if( !yes ) return;
					window.location.reload();
				},
				message: "An error occured. Inform the inspector or reload the page to try again"
			});
		}
	});
	
	
});