/*	Get the size of the svg based on the no. of rows and row length and other parameter.,.*/
function getSvgSize(parameters,prsm,start_pos,end_pos)
{
	let num_of_rows = getNumOfRows(parameters,prsm) ;
	let no_of_blocks = parameters.row_length/parameters.block_length - 1 ;
	let width = parameters.letter_width * parameters.row_length + no_of_blocks*parameters.gap_width + parameters.right_margin + parameters.left_margin;
	if(parameters.show_num)
	{
		width = width + parameters.numerical_width * 2 ;
	}
	if(isShiftAnnotationNeeded(parameters,prsm))
	{
		parameters.row_height = parameters.row_height + 0.2*parameters.row_height;
		parameters.top_margin = 45 ;
	}
	let height = parameters.row_height * num_of_rows + parameters.bottom_margin + parameters.top_margin ;
	let first_position,last_position,start_info = null ,end_info = null ;
	[parameters,first_position, last_position,start_info,end_info] = skip_list(parameters,prsm);
	return [width,height];
}
/* Get number of rows of the sequence based on the row length */
function getNumOfRows(parameters,prsm)
{
	let first_position,last_position,start_info = null ,end_info = null ;
	[parameters,first_position, last_position,start_info,end_info] = skip_list(parameters,prsm);
	let new_sequence_length = last_position - first_position ;
	let num_of_rows = parseInt(new_sequence_length/parameters.row_length) ;
	let skip_acid_count = 0 ;
	/*if(num_of_rows > parseInt(num_of_rows))
	{
		num_of_rows = parseInt(num_of_rows) ;
	}*/
	/*if(start_info != null && parameters.show_skipped_lines)
	{
		skip_acid_count = skip_acid_count ;
	}*/
	if(end_info != null && parameters.show_skipped_lines )
	{
		skip_acid_count = skip_acid_count + 1;
	}
	num_of_rows = num_of_rows + skip_acid_count;
	return num_of_rows ;
}
/* get the sequence on to svg */
function buildSvg(parameters,prsm,id)
{
	let first_residue_position = parseInt(prsm.annotated_protein.annotation.first_residue_position) ;
	let last_residue_position = parseInt(prsm.annotated_protein.annotation.last_residue_position) ;
	let width,height ;
	[width,height] = getSvgSize(parameters,prsm,first_residue_position,last_residue_position) ;
	/*create a group under svg with svgId_g*/
	
	let svgContainer = d3.select("#"+id).attr("width",width)
									.attr("height",height)
									.attr("font-family","'FreeMono',Miltonian,monospace")
									.attr("font-size","16px");
	return [parameters,id] ;
}
function drawAcidonSVG(parameters,prsm,id)
{
	let first_residue_position = parseInt(prsm.annotated_protein.annotation.first_residue_position) ;
	let last_residue_position = parseInt(prsm.annotated_protein.annotation.last_residue_position) ;
	let id_temp = id + "_g" ;
	svgContainer = d3.select("#"+id).append("g")
								.attr("id",id_temp)
								.attr("class",id_temp);
	text = 	svgContainer.selectAll("text");		
	
	let first_position,last_position,start_info = null ,end_info = null ;
	/*	Get the new first and last position based on the amount of acids are needed to be skipped */
	[parameters,first_position, last_position,start_info,end_info] = skip_list(parameters,prsm);					
	prsm.annotated_protein.annotation.residue.forEach(function(input,index){
		if(parseInt(input.position) >= first_position && parseInt(input.position) < last_position )
		{
			let x,y ;
			/*	Get the x and y coordinates of the acid position	*/
			[x,y] = calibrateCoordinates(parameters,parseInt(input.position),first_position) ;
			text.data(input.acid)
				.enter()
				.append("text")
				.attr("id",function(d,i){
					return "id_"+id_temp+"_"+input.position ;
				})
				.attr("x", function(d,i){ 
					return x ;
				})
				.attr("y", function(d,i){ 
					return y ;
				})
				.text(function(d,i){
					return d ;
				})
				.style("fill", function(d,i){
					if(parseInt(input.position) < first_residue_position || parseInt(input.position) > last_residue_position)
					{
						return "grey" ;
					}
				})
				.on("mouseover",handleAcidMouseOver)
				.on("mouseout",handleAcidMouseOut)
				.on("click",function(){
					let position = parseInt(input.position) ;
					handleOnClick(prsm,position);
				});
		}
	});
}
function handleAcidMouseOver(d,i){
	d3.select(this)
	.style("cursor","pointer")
	//.style("fill","orange")
	
}
function handleAcidMouseOut(d,i)
{
	d3.select(this)
		.style("cursor","default")
	//	.style("fill","black");
}
function handleOnClick(prsm,position){
	
	d3.selectAll("#tooltip_pop").remove() ;
	
	var div = d3.select("body").append("div")
				    .attr("class", "tooltip")
				    .attr("id","tooltip_pop")
				    .style("opacity", 1);
	
	div.transition()
     .duration(200)
     .style("opacity", .9);
	div .html(
	         '<input type="text" id= "mass_shift" style="width:50px" />' + '<button id="ok" style = "none" type="button">ok</button>'
	         )     
	         .style("left", (d3.event.pageX - 30) + "px")             
	         .style("top", (d3.event.pageY - 45) + "px");
	
	d3.select("#ok").on("click",function(){
				let massShift =  parseFloat(document.getElementById("mass_shift").value) ;
				console.log("massShift : ", massShift, "position : ", position );
				if(!isNaN(massShift))
				{
					peakCalData(prsm,massShift,position)
				}
				d3.select("#tooltip_pop").remove() ;
		});
}

/* Get the terminated/skipped acid information on to the svg */
function skippedAcidNotification(parameters,prsm,id)
{
	let first_position,last_position,start_info = null ,end_info = null ;
	/*	Get the new first and last position based on the amount of acids are needed to be skipped */
	[parameters,first_position, last_position,start_info,end_info] = skip_list(parameters,prsm);
	let svgContainer = d3.select("#"+id+"_g") ;
	let x,y ;
	if(parameters.show_skipped_lines)
	{
		if(!(start_info == null))
		{
			/*	Get the coordinates to write the skip information at the start of acid	*/
			[x,y] = calibrateSkipStart(parameters,first_position,first_position) ;
			svgContainer.append("text")
				.attr("x", x)
				.attr("y", y)
				.text(start_info);
		}
		if(end_info != null)
		{
			/*	Get the coordinates to write the skip information at the end of acid	*/
			[x,y] = calibrateSkipEnd(parameters,last_position,first_position) ;
			svgContainer.append("text")
			.attr("x", x)
			.attr("y", y)
			.text(end_info) ;
		}
	}
}
/* Put the numerical positions at the start and end of each row of the sequence	*/
function getNumValues(para,prsm,id)
{
	let first_position,last_position,start_info = null ,end_info = null ;
	/*	Get the new first and last position based on the amount of acids are needed to be skipped */
	[para,first_position, last_position,start_info,end_info] = skip_list(para,prsm);
	let svgContainer = d3.select("#"+id+"_g") ;
	prsm.annotated_protein.annotation.residue.forEach(function(input,index){
		if(parseInt(input.position) >= first_position && parseInt(input.position) < last_position )
		{
			let x,y ;
			l_position_temp = input.position ;
			/*	write the numerical values only at the start position and end position(this is in the
			 * 	form of 29,59 etc.,. as the data starts with 0 as 1st element) 							*/
			if(parseInt(l_position_temp)%(para.row_length) ==  0 || parseInt(l_position_temp)%(para.row_length)  ==  (para.row_length-1) 
									|| parseInt(l_position_temp) == (last_position-1))
			{
				let id_temp ;
				position = parseInt(input.position) +1;
				if(parseInt(input.position)%para.row_length ==  0)
				{
					/*	Get the coordinates of left numerical	*/
					[x,y] = calibrateLeftNum(para,parseInt(l_position_temp),first_position) ;
					x = x ;//- para.anno_width ;
					id_temp = "left_align" ;
				}
				else
				{
					/*	Get the coordinates of right numerical	*/
					[x,y] = calibrateRightNum(para,parseInt(l_position_temp),first_position) ;
					id_temp = "right_align" ;
					//x = x + para.anno_width ;
					//position =  position ; 
				}
				svgContainer.append("text")
					.attr("id", id_temp)
					.attr("x",x)
					.attr("y",y)
					.text(function(d,i){
						return position ;
					})
					.style("text-anchor",function(d,i){
						/*	Align the left numerical towards left side */
						if(id_temp == "left_align")
						{
							return "end" ;
						}
						return null ;
					});
			}
		}
	})
}
/* Draw annotations*/
function annotations(para,prsm,id)
{
	/*	Get annotation position	and information */
	var annotations = json2CleavagePositions(prsm) ;
	/* 	Drawing Annotation on to screen using D3 polyline	*/
	annotations.forEach(function(annotation,index){
		let l_charge = getIonCharge(annotations,annotation.position);
		
		if(annotation.exist_n_ion == "1" && annotation.exist_c_ion == "1")
		{
			drawAnnotation_YB(para,prsm,annotation,l_charge,id) ;
		}
		else
		{
			if(annotation.exist_n_ion == "1")
			{
				drawAnnotation_B(para,prsm,annotation,l_charge,id) ;
			} 
			if(annotation.exist_c_ion == "1")
			{
				drawAnnotation_Y(para,prsm,annotation,l_charge,id) ;
			}
		}
	})
}
/*	Draw the annotation when the ion type is B	*/
function drawAnnotation_B(para,prsm,annotation,l_charge,id)
{
	let first_position,last_position,start_info = null ,end_info = null ;
	[para,first_position, last_position,start_info,end_info] = skip_list(para,prsm);
	let x,y ;
	[x,y] = calibrateCoordinates(para,parseInt(annotation.position)-1,first_position);
	x = x + (para.letter_width/2) ;
	let coordinates = (x-2)+","+(y-13)+ " " +(x+4)+","+ (y-11)+" "+(x+4)+","+(y+2);
	
	drawAnnotation(annotation,l_charge,id,coordinates,x,y);
}
/* Draw the annotation when the ion type is Y*/
function drawAnnotation_Y(para,prsm,annotation,l_charge,id)
{
	let first_position,last_position,start_info = null ,end_info = null ;
	[para,first_position, last_position,start_info,end_info] = skip_list(para,prsm);
	let x,y ;
	[x,y] = calibrateCoordinates(para,parseInt(annotation.position)-1,first_position);
	x = x + (para.letter_width/2) ;
	let coordinates = (x+4)+","+ (y-11)+" "+(x+4)+","+(y+2)+ " "+(x+10) + ","+(y+5);
	drawAnnotation(annotation,l_charge,id,coordinates,x,y);
	
}
function drawAnnotation_YB(para,prsm,annotation,l_charge,id)
{
	let first_position,last_position,start_info = null ,end_info = null ;
	[para,first_position, last_position,start_info,end_info] = skip_list(para,prsm);
	let x,y ;
	[x,y] = calibrateCoordinates(para,parseInt(annotation.position)-1,first_position);
	x = x + (para.letter_width/2) ;
	let coordinates =  (x-2)+","+(y-13)+ " " + (x+4)+","+ (y-11)+" "+(x+4)+","+(y+2)+ " "+(x+10) + ","+(y+5);
	drawAnnotation(annotation,l_charge,id,coordinates,x,y);
}
function drawAnnotation(annotation,l_charge,id,coordinates,x,y)
{
	let svgContainer = d3.select("#"+id+"_g");
	let l_polyline = svgContainer.append("polyline")
							.attr("points", coordinates)
							.style("fill", "none")
							.style("stroke", "1e90ff")
							.style("stroke-width", "1");	
		/*	Rectangle to have flexible on click and on mouse actions	*/
		svgContainer.append("rect")
					.attr("x", x)
					.attr("y", y-14)
					.attr("width", 13)
					.attr("height", 23)
					.style("opacity", 0)
					.attr("cursor", "pointer")
					.on("click",function(){
						input = annotation.ion_position;
						showIonPeaks(input);
					})
					.on("mouseover", function(){
						appendTooltip(l_charge);
					})
					.on("mouseout", function(d){
						removeToolTip();	
					});
}
function appendTooltip(charge)
{
	var div = d3.select("body").append("div")	
								.attr("class", "tooltip")				
								.style("opacity", 0); 
		div.transition()		
			.duration(10)		
			.style("opacity", .9);
		div.html(charge)	
		.style("left", (d3.event.pageX)  + "px")		
		.style("top", (d3.event.pageY - 28)+ "px") ;
}
function removeToolTip()
{
	d3.selectAll(".tooltip").remove();
}
/*	get the terminated acid information	*/
function skip_list(para,prsm)
{
	let l_afirst_residue_position = parseInt(prsm.annotated_protein.annotation.first_residue_position) ;
	let l_alast_residue_position = parseInt(prsm.annotated_protein.annotation.last_residue_position) ;	
	let l_asequence_length = parseInt(prsm.annotated_protein.annotation.protein_length) ;
	let new_first_position = 0 ;
	let initial_skip_count = 0 ;
	let start_info = null ;
	if(l_afirst_residue_position > (parseInt(para.row_length) + l_afirst_residue_position%parseInt(para.row_length) ) )
	{
		new_first_position = l_afirst_residue_position - ((l_afirst_residue_position%para.row_length)+para.row_length );
		initial_skip_count = new_first_position ;
		start_info = "... "+initial_skip_count + " amino acid residues are skipped at the N-terminus ... ";
	}
	let new_last_position = l_alast_residue_position + 1 ;
	let final_skip_count = 0 ;
	let end_info = null ;
	if(l_alast_residue_position+(para.row_length - (l_alast_residue_position%para.row_length) +para.row_length) < l_asequence_length)
	{
		new_last_position = l_alast_residue_position+( para.row_length - (l_alast_residue_position%para.row_length) + para.row_length)  ;
		end_skip_count = l_asequence_length-new_last_position ;
		end_info = "... "+end_skip_count + " amino acid residues are skipped at the C-terminus ... ";
	}
	else if(l_alast_residue_position+1 < l_asequence_length)
	{
		new_last_position = l_asequence_length-1;
	}
	return[para,new_first_position,new_last_position,start_info,end_info];
}
 /*	Draw the annotations to show the start and end position of the sequence	*/
function drawAnnoOfStartEndPosition(para,prsm,id)
{
	let first_residue_position = parseInt(prsm.annotated_protein.annotation.first_residue_position) ;
	let last_residue_position = parseInt(prsm.annotated_protein.annotation.last_residue_position) ;
	let sequence_length = parseInt(prsm.annotated_protein.annotation.protein_length) ;
	let first_position,last_position,start_info = null ,end_info = null ;
	[para,first_position, last_position,start_info,end_info] = skip_list(para,prsm);
	let svgContainer = d3.select("#"+id+"_g");
	let new_virtual_postion = first_residue_position - first_position ; 
	let non_data_indicator = false;
	if(first_residue_position != 0)
	{
		let x,y ;
		[x,y] = calibrateCoordinates(para, first_residue_position-1, first_position );
		x = x + (para.letter_width/2) ;
		let first_position_coordinates = (x)+","+(y+2)+ " " +(x+5)+","+ (y+2)+" "+(x+5)+","+(y-12)+ " "+(x) + ","+(y-12);
		svgContainer.append("polyline")
					.attr("class","none")
					.attr("points", first_position_coordinates)
					.style("fill", "none")
					.style("stroke", "red")
					.style("stroke-width", "1.3") ;
	}
	if((sequence_length != last_residue_position +1 ) )
	{
		let x,y ;
		[x,y] = calibrateCoordinates(para, last_residue_position, first_position );
		x = x + (para.letter_width/2) ;
		let first_position_coordinates = (x+7)+","+(y-12)+ " " +(x+2)+","+ (y-12)+" "+(x+2)+","+(y+2)+ " "+(x+7) + ","+(y+2);
		svgContainer.append("polyline")
					.attr("class","none")
					.attr("points", first_position_coordinates)
					.style("fill", "none")
					.style("stroke", "red")
					.style("stroke-width", "1.3") ;
	}
}
 /*	Color the background of the occurence	*/
function massShiftBackgroundColor(para,prsm,id)
{
	let Background_color = json2BackgroundColorArray(prsm);
	console.log("Background_color : ", Background_color);
	let non_data_indicator = false ;
	let first_position,last_position,start_info = null ,end_info = null ;
	[para,first_position, last_position,start_info,end_info] = skip_list(para,prsm);
	Background_color.forEach(function(input,index){
		let left_position = parseInt(input.left_position) ;
		let right_position = parseInt(input.right_position) ;
		let annotation = input.anno ;
		let isShiftNeeded = shiftAnnotation(para,prsm,index) ;
		while(left_position < right_position)
		{
			let leftPosition, rightPosition ;
			[leftPosition,rightPosition] = getRightPosition(para,left_position,right_position) ;
			rightPosition = rightPosition - 1 ;
			let x,y;
			[x,y] = calibrateCoordinates(para, leftPosition ,first_position);
			let x1,y1;
			[x1,y1] = calibrateCoordinates(para, rightPosition ,first_position);
			let width = x1-x;
			rect_Backgroundcolor(x,y,id,width,para);
			MassShift(x,y,id,annotation,isShiftNeeded);
			left_position = parseInt(rightPosition) + 1 ;
			annotation = "";
			//break ;
		}
	})
	
}
/*	Get the right end position to color the background color when there is a change of row*/
function getRightPosition(para,leftPosition, rightPosition)
{
	if( parseInt(rightPosition/para.row_length) > parseInt(leftPosition/para.row_length) )
	{
		rightPosition = (parseInt(leftPosition/para.row_length)+1)*para.row_length ;
	}
	
	return [leftPosition, rightPosition] ;
}
/* Modifying the color array to match the array of letters and positions */
function addColorToFixedPtms(para,prsm,id){
	let known_Change = json2FixedPtmOccurence(prsm);
	known_Change.forEach(function(position,i){
		l_class_id ="#id_"+id+"_g_"+position ;
		d3.select(l_class_id)
			.style("fill", "red")
	})
					
}
/* Get the charge of the Ion */
function getIonCharge(l_annotation_array,position){
	let l_charge = "";
	for(let j=0;j<l_annotation_array.length;j++){
		if(position == l_annotation_array[j].position )
		{
			 l_charge = l_charge + l_annotation_array[j].ion_type+l_annotation_array[j].ion_display_position
			 						+" "+l_annotation_array[j].peak_charge+"+ " ;
		}
	}
	return l_charge ;
}

/* Code to color the background of a occurence acids */
function rect_Backgroundcolor(x,y,id,width,para){
	console.log("in Backgroung rect");
	/*	font-size 16px is equal to 12pt	*/
	let font_width = 12 ;
	/*	to draw the rect color uniformly */
	let font_height = 15 ;
	
	let svgContainer = d3.selectAll("#"+id);
	console.log("svgContainer : ",svgContainer, " id : ", id );
	svgContainer.append("rect")
					.attr("class","bgColor")
					.attr("x", x)
					.attr("y", y-font_height)
					.attr("width", width+font_width)
					.attr("height", 20)
					.attr("dy", "0em")
					.style("fill", para.background_color)
					.style("fill-opacity", ".4")
					.style("stroke-width", "1.5px");
}
/* MassShift value at the top of the acids */
function MassShift(x,y,id,value,isShift)
{
	let dy = -1.2 ;
	
	if(isShift)
	{
		dy = 1.7*dy ;
	}
	dy = dy+"em" ;
	let svgContainer = d3.select("#"+id);
	svgContainer.append("text")
				   .attr("x", x)
				   .attr("y", y)
				   .attr("dy", dy) 
				   .text(function(){
					   return value ;
				   })
				   .attr("font-size","15px");;
}
/* shift the position of the mass shift when overlapping one another*/
function shiftAnnotation(para,prsm,index)
{
	let isshiftNeeded = false ;
	let bgColorAndMassShift = json2BackgroundColorArray(prsm) ; 
	/*	font-size 16px is equal to 12pt*/
	let font_width = 12 ;
	let first_position, last_position,start_info,end_info ;
	[para,first_position, last_position,start_info,end_info] = skip_list(para,prsm);
	for(let i = 1; i<bgColorAndMassShift.length;i++)
	{
		if(i == index)
		{
			let x1,y1 ;
			[x1,y1] = calibrateCoordinates(para,parseInt(bgColorAndMassShift[i].left_position),first_position) ;
			
			let x2,y2 ;
			[x2,y2] = calibrateCoordinates(para,parseInt(bgColorAndMassShift[i-1].left_position),first_position) ;
			/* subtract -2 for CSS and alignment purpose*/
			if((Math.abs(x2-x1) + font_width )< bgColorAndMassShift[i-1].anno.length*(font_width-2) )
			{
				isshiftNeeded = true ;
			}
		}
	}
	return isshiftNeeded ;
}
function isShiftAnnotationNeeded(para,prsm)
{
	let isshiftNeeded = false ;
	let bgColorAndMassShift = json2BackgroundColorArray(prsm) ; 
	/*	font-size 16px is equal to 12pt*/
	let font_width = 12 ;
	let first_position, last_position,start_info,end_info ;
	[para,first_position, last_position,start_info,end_info] = skip_list(para,prsm);
	for(let i = 1; i<bgColorAndMassShift.length;i++)
	{
			let x1,y1 ;
			[x1,y1] = calibrateCoordinates(para,parseInt(bgColorAndMassShift[i].left_position),first_position) ;
			
			let x2,y2 ;
			[x2,y2] = calibrateCoordinates(para,parseInt(bgColorAndMassShift[i-1].left_position),first_position) ;
			/* subtract -2 for CSS and alignment purpose*/
			if((Math.abs(x2-x1) + font_width )< bgColorAndMassShift[i-1].anno.length*(font_width-2) )
			{
				isshiftNeeded = true ;
				break ;
			}
	}
	return isshiftNeeded ;
}
