/* globals structureData, createNGLViewer, $ */
$(window).on("load", function() {
	$('.viewport1').each(async function() {
		let proteinViewer = createNGLViewer(this, {structureData: structureData});
		this.proteinViewer = proteinViewer;
		proteinViewer.addHandler('model-loaded', function(ev) {
			let infoElem = $('.structureInfo');
			// Assembly
			let assemblyElem = infoElem.find('.assembly');
			if (assemblyElem.length) {
				updateAssemblyList(ev.structure, proteinViewer.stage, assemblyElem);
			}
			// Title
			let data = proteinViewer.getStructureData(ev.structure);
			let elem = infoElem.find('.structureSelector[data-for="viewport1"] .structureTitle');
			elem.html(data['title']);
			// Variants
			infoElem.find('.variants.clinical').html('Clinical (#='+data['variantCount']['c']['variants']+')');
			infoElem.find('.variants.population').html('Population (#='+data['variantCount']['p']['variants']+')');
			infoElem.find('.alphavariants.pathogenic').html('Pathogenic (#='+data['variantCount']['ac']['variants']+')');
			infoElem.find('.alphavariants.benign').html('Benign (#='+data['variantCount']['ap']['variants']+')');
			// Structure warning
			structureWarning(ev.structure);
		});
		proteinViewer.addHandler('variant-changed', function(ev) {
			$('.structureInfo #variantLegend').html($(ev.legendData));
		});
		proteinViewer.addHandler('color-changed', function(ev) {
			$('.structureInfo  #colorLegend').html(ev.legendData);
		});
		proteinViewer.addHandler('highlight-changed', function(ev) {
			let slide = $('.color.highlight');
			if (slide.hasClass('active')) {
				slide.trigger('toggle');
			} else {
				slide.trigger('click');
			}
		});
		let transcript = $('.antigen_view .tab.selected').attr('name').replace('_', '-');
		let structures = getTranscriptMappedStructures(transcript);
		await proteinViewer.run(structures[0]);
	});
	$('.NGLFullscreen').on('click', function() {
		if (!document.fullscreenElement) {
			attemptNGLFullscreen($(this).closest('.NGLViewer').attr('id'));
		} else if (document.exitFullscreen) {
			document.exitFullscreen();
		}
	});
	addStructureFullscreenHandler();

	const targetNode = document.getElementsByClassName("antigen_view")[0];
	// Options for the observer (which mutations to observe)
	const config = { attributes: true, childList: true, subtree: true };
	// Callback function to execute when mutations are observed
	const callback = (mutationList) => {
		let c = debounceEvent(function(elem, mutation) {handleTranscriptDisplaySwitch(elem, mutation.target);}, 50);
		for (const mutation of mutationList) {
			if (mutation.type === "attributes" && mutation.target.classList.contains('tab_content') && !mutation.target.classList.contains('hidden')) {
				if (!mutation.target.querySelector('svg.transcript')) {
					let objectElem = mutation.target.querySelector('iframe.transcript_svg');
					load_object_to_svg(objectElem);
				}
				c(undefined, mutation);
			}
		}
	};
	// Create an observer instance linked to the callback function
	const observer = new MutationObserver(callback);
	// Start observing the target node for configured mutations
	observer.observe(targetNode, config);

	$('.transcript_svg').each(function() {
		load_object_to_svg(this);
	});

	$('.sequence_svg').each(function() {
		load_object_to_svg_seq(this);
	});
	let proteinBrowser = $('#protein_browser');
	proteinBrowser.on('click', '.transcriptView', function(e) {
		const transcriptElement = $(e.target).closest('.transcript').get(0);
		const name = transcriptElement.dataset.name.replace('-', '_');
		$('.antigen_view .tab[name="'+name+'"] span').trigger('click');
	});

	proteinBrowser.on('transcriptChanged', function(e, data) {
		let transcript = data.transcript;
		let view = $('.transcriptView');
		let transcripts = view.find('.transcript');
		transcripts.removeClass('selected');
		var tPos = transcripts.filter('.'+transcript).addClass('selected').position().top;
		var vPos = view.position().top;
		$('#transcriptName').html(transcript);
		$('#transcriptOffset').css('height', (tPos-vPos+5)+'px');
	});
	proteinBrowser.trigger('transcriptChanged', {transcript: $('.antigen_view .tab.selected').attr('name')});

	// handleTranscriptDisplaySwitch(undefined, $('.antigen_view .tab_content:not(.hidden)').get(0));
	$('.antigen_view').on('mouseover', 'svg.transcript.mapped rect.highlightable', function() {
		if (!$(this).attr('hovered')) {
			let t = $(this).attr('title');
			$(this).attr('title', t+'<br><br>Click to highlight in 3D structure');
			$(this).attr('hovered', true);
		}
	});
	$('.antigen_view').on('click', 'svg.transcript.mapped rect.highlightable', function() {
		var aaStart = $(this).data('aaStart');
		var aaStop = $(this).data('aaStop');
		var name = $(this).data('name');
		var color;
		if (!$(this).hasClass('antigen')) {
			color = parseInt($(this).attr('fill').slice(1), 16);
		}
		let isAntibody = false;
		if ($(this).data('type') === 'antibody') {
			isAntibody = true;
		}
		var transcript = $(this).closest('svg').data('transcript');
		$('.viewport1, .viewport2').each(function() {
			let viewName = name;
			if (isAntibody) {
				let data = this.proteinViewer.getStructureData(this.proteinViewer.getLoadedStructure());
				for (let ab in data.antigens) {
					if (data.antigens[ab].ab === name) {
						if (data.antigens[ab].identity_percent !== 100) {
							viewName = name + ' - match percentage: ' + data.antigens[ab].identity_percent + '%';
						}
						break;
					}
				}
			}
			$(this).trigger('highlightSection', {
				'transcript': transcript,
				'name': viewName,
				'startPos': aaStart,
				'stopPos': aaStop,
				'color': color
			});
		});
	});
	$('body').on('click', 'div.colorLegendEntry.structureHL', function() {
		var key = $(this).data('key');
		$('.viewport1, .viewport2').each(function() {
			$(this).trigger('highlightSection', {
				'key': key,
			});
		});
	});
});

function protein_browser_tab_changed(elem, content) {
	const name = $(elem).closest('.tab').attr('name');
	$('#protein_browser').trigger('transcriptChanged', {transcript: name});
}

function load_object_to_svg(objectElem) {
	var svg = $(objectElem.contentDocument).find('svg');
	svg.attr('id', $(objectElem).attr('id')+'_svg');
	svg.attr('data-transcript', $(objectElem).attr('data-transcript'));
	let mapped = $(objectElem).hasClass('mapped');
	if (mapped) {
		svg.addClass('mapped');
	}
	svg.prependTo($(objectElem).parent());
	if (svg.length) {
		$(objectElem).hide();
		objectElem.parentNode.removeChild(objectElem);
	}
	if (svg.closest('.tab_content').is(':visible') && mapped) {
		$('#NGLViewer').show();
	}
}

function load_object_to_svg_seq(objectElem) {
	var svg = $(objectElem.contentDocument).find('svg');
	var parentWidth = $(objectElem).parent().width();
	svg.attr('id', $(objectElem).attr('id')+'_svg').css({width:'100%'});
	svg.prependTo($(objectElem).parent());
	if (svg.length) {
		$(objectElem).hide();
		objectElem.parentNode.removeChild(objectElem);
	}
}

// eslint-disable-next-line no-unused-vars
async function handleTranscriptDisplaySwitch(elem, content) {
	// called when switching tab in protein browser
	var svg = $(content).find('svg');
	if (svg.length) {
		let viewport = document.querySelector('.viewport1');
		var msgElem = $('#structureMessage');
		var viewerDiv = $('#NGLViewer');
		let structures = getTranscriptMappedStructures(svg.data("transcript"));
		if (structures.length > 0) {
			viewport.proteinViewer.addOnceHandler('model-loaded', function() {
				$(viewport).trigger('resetHighlight');
				viewerDiv.show();
				msgElem.hide();
			});
			// await viewport.proteinViewer.run($('div.structureSelector select').val());
			viewport.proteinViewer.loadmodel(structures[0]);
		} else {
			viewerDiv.hide();
			if (msgElem.length) {
				msgElem.show();
			} else {
				$('<p id="structureMessage">Transcript not mapped to available structure(s)</p>').appendTo(viewerDiv.parent());
			}
		}
	}
}

function structureWarning(structure) {
	// FIXME: quickfix
	let svg = $('.antigen_view .tab_content:not(.hidden) svg');
	// let structure = $('.viewport1')[0].viewer.getLoadedStructure();
	let info = $('#structureTranscriptInfo');
	let newData = '';
	if (structure) {
		let structureData = document.querySelector('.viewport1').proteinViewer.getStructureData(structure);
		let s_length = structureData.structureLength;
		let t_length;
		if (structureData.transcriptMappings.hasOwnProperty(svg.data("transcript"))) {
			t_length = structureData.transcriptMappings[svg.data("transcript")].aa_seq_length;
		}
		if (t_length && s_length > t_length) {
			newData = '<p><span style="font-weight: bold">Notice:</span></p><br><div>Transcript is a subsequence of the displayed structure</div>';
		}
	}
	if (newData !== info.html()) {
		info.html(newData);
	}
}

function getTranscriptMappedStructures(transcript) {
	let o = [];
	let structureData = document.querySelector('.viewport1').proteinViewer.getStructureDataEntries();
	Object.keys(structureData).forEach(function(key) {
		let structure = structureData[key];
		if (structure.transcriptMappings.hasOwnProperty(transcript)) {
			o.push(key);
		}
	});
	return o;
}

function attemptNGLFullscreen(id) {
	const element = document.getElementById(id);
	if (!document.fullscreenElement) {
		element.dataset.originalWidth = element.clientWidth.toString();
		element.dataset.originalHeight = element.clientHeight.toString();
		element.querySelectorAll('canvas').forEach(function(e) {
			if (typeof e.dataset.originalWidth === "undefined") {
				e.dataset.originalWidth = e.width;
				e.dataset.originalHeight = e.height;
			}
			delete e.width;
			delete e.height;
			delete e.style.width;
			delete e.style.height;
		});
	}
	if (element.requestFullscreen) {
		element.requestFullscreen();
	} else if (element.mozRequestFullScreen) {
		element.mozRequestFullScreen();
	} else if (element.webkitRequestFullscreen) {
		element.webkitRequestFullscreen();
	} else if (element.msRequestFullscreen) {
		element.msRequestFullscreen();
	} else {
		throw new Error('Cannot open fullscreen');
	}
}
function addStructureFullscreenHandler() {
	document.addEventListener('fullscreenchange', function() {
		if (!document.fullscreenElement) {
			document.getElementById('NGLViewer').querySelectorAll('canvas').forEach(function(e) {
				e.width = e.dataset.originalWidth;
				e.style.width = e.dataset.originalWidth+'px';
				e.height = e.dataset.originalHeight;
				e.style.height = e.dataset.originalHeight+'px';
			});
		}
		document.querySelectorAll('.viewport1, .viewport2').forEach(function(e) {
			e.proteinViewer.stage.handleResize();
		});
	});
}
function updateAssemblyList(structure, stage, assemblyElem) {
	assemblyElem = $(assemblyElem);
	assemblyElem.empty();
	let components = stage.getComponentsByName(structure);
	let assemblies;
	if (components.list.length) {
		assemblies = components.list[0].structure.biomolDict;
	}
	assemblyElem.append(`<option value="">All</option>`);

	if (assemblies) {
		Object.keys(assemblies).forEach(function (k) {
			assemblyElem.append(`<option value="${k}">${k}</option>`);
		});
	}
}
function debounceEvent(callback, delay = 250) {
	let timeoutId;
	return (...args) => {
		clearTimeout(timeoutId);
		timeoutId = setTimeout(() => {
			callback(...args);
		}, delay);
	};
}