<?php
	//special sorting of the cell name (keys of an associative array) : "B1..9,b1..9,a9..1,A9..1
	function mySortByCellKey($array)
	{
		//array sorted to return
		$arraySorted = array();
		//comparison of cell names
		function cmp($a,$b)
		{
			$keyA = $a;
			$keyB = $b;
			switch ($keyA[0])
			{
				case 'B':
					$valueA = 4;
					break;
				case 'b':
					$valueA = 3;
					break;
				case 'a':
					$valueA = 2;
					break;
				case 'A':
					$valueA = 1;
					break;
			}
			switch ($keyB[0])
			{
				case 'B':
					$valueB = 4;
					break;
				case 'b':
					$valueB = 3;
					break;
				case 'a':
					$valueB = 2;
					break;
				case 'A':
					$valueB = 1;
					break;
			}
			//if the line is the same, compare cells numbers
			if($keyA[0]==$keyB[0])
			{
				$subA = substr($keyA,1,strlen($keyA));
				$arraySubA = explode(".",$subA);
				$subB = substr($keyB,1,strlen($keyA));
				$arraySubB = explode(".",$subB);
				//sort ascendant
				if($keyA[0]=='B'||$keyA[0]=='b')
				{
					if($arraySubA[0]==$arraySubB[0])
					{
						return ($arraySubA[1] > $arraySubB[1]) ? +1 : -1;
					}
					else
					{
						return ($subA > $subB) ? +1 : -1;
					}
				}
				//sort descendant
				if($keyA[0]=='A'||$keyA[0]=='a')
				{
					if($arraySubA[0]==$arraySubB[0])
					{
						return ($arraySubA[1] < $arraySubB[1]) ? +1 : -1;
					}
					else
					{
						return ($subA < $subB) ? +1 : -1;
					}
				}
			}
			//else return value of the defined order
			return ($valueA < $valueB) ? +1 : -1;
		}
		//array containig keys of the array to sort
		$arrayKey = array_keys($array);
		//sort keys on the special order
		usort($arrayKey, "cmp");
		//take the key sorted and assign value of the array to sort to the sorted array to return
		foreach($arrayKey as $sortedKey)
		{
			$arraySorted[$sortedKey] = $array[$sortedKey];
		}
		return $arraySorted;
	}
	
	//create color and save to no recreate it (php can display only a limited number of colors)
	function createColor($image,$c1,$c2,$c3)
	{
		//see if color already exists
		$color = imagecolorexact($image,$c1,$c2,$c3);
		if($color==-1)
		{
			//color does not exist; allocate a new one
			$color = imagecolorallocate($image,$c1,$c2,$c3);
		}
		return $color;
	}
	
	/**
	 * Assign a color and a thickness depending of a contact value.
	 * @param $im Image to assign color
	 * @param $contact Contact value
	 * @return array Associative array containing color and thickness
	 */ 
	function colorContact($im,$contact)
	{
		//array to return
		$arrayReturn = array();
		//color to return
		$color = null;
		//line thickness to return
		$thickness = null;
		if(is_null($contact))
		{
			$color = createColor($im,0,0,0);
		}
		else
		{
			switch($contact)
			{
				case ($contact<250):
					$color = createColor($im,0,110,255);
					$thickness = 1;
					break;
				case ($contact<500):
					$color = createColor($im,0,170,251);
					$thickness = 2;
					break;
				case ($contact<750):
					$color = createColor($im,0,255,181);
					$thickness = 3;
					break;
				case ($contact<1000):
					$color = createColor($im,0,224,10);
					$thickness = 4;
					break;
				case ($contact<1250):
					$color = createColor($im,180,230,4);
					$thickness = 5;
					break;
				case ($contact<1500):
					$color = createColor($im,255,217,0);
					$thickness = 6;
					break;
				case ($contact<1750):
					$color = createColor($im,230,184,0);
					$thickness = 7;
					break;
				case ($contact<2000):
					$color = createColor($im,251,116,0);
					$thickness = 8;
					break;
				case ($contact<2250):
					$color = createColor($im,251,59,0);
					$thickness = 9;
					break;
				case ($contact<2500):
					$color = createColor($im,196,0,99);
					$thickness = 10;
					break;
				case ($contact>=2500):
					$color = createColor($im,130,0,191);
					$thickness = 11;
					break;
					
				default :
					$color = createColor($im,0,0,0);
					$thickness = 1;
					break;
			}
		}
		$arrayReturn["color"] = $color;
		$arrayReturn["thickness"] = $thickness;
		return $arrayReturn;
	}
	
	/**
	 * Diplay a legend on an image
	 * @param $im Image to display legend on
	 * @param $coordinates Array of four coordinates to map the legend
	 * @return null
	 */
	function displayLegend($im,$coordinates)
	{
		$x = $coordinates[0];
		$y = $coordinates[1];
		$x2 = $coordinates[2];
		$y2 = $coordinates[3];
		$step = 30;
		$color = createColor($im,0,110,255);
		imagefilledrectangle($im,$x,$y,$x2,$y2,$color);
		$color = createColor($im,0,170,251);
		imagefilledrectangle($im,$x,$y+1*$step,$x2,$y2+1*$step,$color);
		$color = createColor($im,0,255,181);
		imagefilledrectangle($im,$x,$y+2*$step,$x2,$y2+2*$step,$color);
		$color = createColor($im,0,224,10);
		imagefilledrectangle($im,$x,$y+3*$step,$x2,$y2+3*$step,$color);
		$color = createColor($im,180,230,4);
		imagefilledrectangle($im,$x,$y+4*$step,$x2,$y2+4*$step,$color);
		$color = createColor($im,255,217,0);
		imagefilledrectangle($im,$x,$y+5*$step,$x2,$y2+5*$step,$color);
		$color = createColor($im,230,184,0);
		imagefilledrectangle($im,$x,$y+6*$step,$x2,$y2+6*$step,$color);
		$color = createColor($im,224,140,0);
		imagefilledrectangle($im,$x,$y+7*$step,$x2,$y2+7*$step,$color);
		$color = createColor($im,251,59,0);
		imagefilledrectangle($im,$x,$y+8*$step,$x2,$y2+8*$step,$color);
		$color = createColor($im,196,0,99);
		imagefilledrectangle($im,$x,$y+9*$step,$x2,$y2+9*$step,$color);
		$color = createColor($im,130,0,191);
		imagefilledrectangle($im,$x,$y+10*$step,$x2,$y2+10*$step,$color);
		//write text
		$colorText = createColor($im,0,0,0);
		//police size
		$textSize = 28;
		//move the text on y axe
		$textStepY = 5*3;
		//move the text on x axe
		$textStepX = 115;
		$textLegend = "0";
		$fontPath = "./fonts/arial.ttf";
		imagettftext($im,$textSize,0,$x+$textStepX,$y+1*$step-$textStepY,$colorText,$fontPath,$textLegend);
		$textLegend = "500";
		imagettftext($im,$textSize,0,$x+$textStepX,$y+3*$step-$textStepY,$colorText,$fontPath,$textLegend);
		$textLegend = "1000";
		imagettftext($im,$textSize,0,$x+$textStepX,$y+5*$step-$textStepY,$colorText,$fontPath,$textLegend);
		$textLegend = "1500";
		imagettftext($im,$textSize,0,$x+$textStepX,$y+7*$step-$textStepY,$colorText,$fontPath,$textLegend);
		$textLegend = "2000";
		imagettftext($im,$textSize,0,$x+$textStepX,$y+9*$step-$textStepY,$colorText,$fontPath,$textLegend);
		$textLegend = "2500";
		imagettftext($im,$textSize,0,$x+$textStepX,$y+11*$step-$textStepY,$colorText,$fontPath,$textLegend);
		return null;
	}
	
	/**
	 * Not working. Should replace imagelinethick.
	 * @param $im Image to display on
	 * @param $arrayCoordinates Coordinates of two points to draw line between
	 * @param $color Color to assign to the line
	 * @param $thickness Thickness of the line
	 * @return null
	 */
	function drawLine($im,$arrayCoordinates,$color,$thickness)
	{
		$thickness = $thickness*3;
		$X = $arrayCoordinates[0];
		$Y = $arrayCoordinates[1];
		$X2 = $arrayCoordinates[2];
		$Y2 = $arrayCoordinates[3];
		//calculate angle between en two positions cells
		if($Y==$Y2)
		{
			$midThickness = 0.1;
			imagefilledrectangle($im,$X2-$midThickness,$Y2,$X2+$midThickness,$Y2,$color);
			return null;
		}
		else
		{
			$angle = atan(abs($X-$X2)/abs($Y-$Y2));
			$XTransformated = $thickness*cos(-abs($angle))/2;
			$YTransformated = $thickness*sin(-abs($angle))/2;
			$arrayPoints = array($X-$XTransformated,$Y-$YTransformated,
				$X2-$XTransformated,$Y2-$YTransformated,
				$X2+$XTransformated,$Y2+$YTransformated,
				$X+$XTransformated,$Y+$YTransformated
			);
		}
		imagefilledpolygon($im,$arrayPoints,4,$color);
		return null;
	}
	
	/**
	 * @param $image Image to display on
	 * @param $x1 Coordinate of two points to draw line between
	 * @param $y1 Coordinate of two points to draw line between
	 * @param $x2 Coordinate of two points to draw line between
	 * @param $y2 Coordinate of two points to draw line between
	 * @param $color Color to assign to the line
	 * @param $thick Thickness of the line
	 * @return null
	 */
	function imagelinethick($image,$x1,$y1,$x2,$y2,$color,$thick=1)
	{
		if($thick==1)
		{
			imageline($image, $x1, $y1, $x2, $y2, $color);
			return null;
		}
		
		$t = 2.5*$thick/2-0.5;
		if($x1==$x2||$y1==$y2)
		{
			imagefilledrectangle($image,round(min($x1,$x2)-$t),round(min($y1,$y2)-$t),round(max($x1,$x2)+$t),round(max($y1,$y2)+$t),$color);
			return null;
		}
		$k = ($y2-$y1)/($x2-$x1);
		$a = $t/sqrt(1+pow($k,2));
		$points = array(round($x1-(1+$k)*$a),round($y1+(1-$k)*$a),
			round($x1-(1-$k)*$a),round($y1-(1+$k)*$a),
			round($x2+(1+$k)*$a),round($y2-(1-$k)*$a),
			round($x2+(1-$k)*$a),round($y2+(1+$k)*$a));
		imagefilledpolygon($image, $points, 4, $color);
		return null;
	}
	
	/**
	 * Create an image of the contact in a developmental stage
	 * @param $arrayCellRelationship Array containing cell relationship with contact (key: cell object =>( key: cell subject => contact value)
	 * @param $h Image size
	 * @param $w Image size
	 * @param $mode Choose to display big contact in first plan
	 * @return null
	 */
	function display_network($arrayCellRelationship,$h,$w,$mode=false)
	{
		//test if relationships exist
		if(count($arrayCellRelationship)==0)
		{
			print("<h2>No relationship between cells for this stage</h2>");
			return;
		}
		//create the image
		$im = imagecreate($h+200,$w+100);
		//white background
		$background = imagecolorallocate($im,255,255,255);
		imagecolortransparent($im,$background);
		//center of the image
		$centreX = $w/2;
		$centreY = $h/2;
		//radius of the circle
		$R = ($h*2)/5;
		//radius of the circle to display cells names
		$Rp = ($h*2)/5 + ($h/25);
		//angle separating two cells positions
		$alpha = 360/count($arrayCellRelationship);
		//angle for each cell
		$unit = 0;
		//array to record position to draw black points
		$arrayPoint = array();
		//count the number of points positions
		$cptPoint = 0;
		//calculate coordinates of each cell
		foreach(array_keys($arrayCellRelationship) as $nameCell)
		{
			$X = $R*cos(deg2rad(90)-deg2rad($unit))+$centreX;
			$Y = $R*sin(deg2rad(90)-deg2rad($unit))+$centreY;
			$arrayPoint[$cptPoint]["originalX"] = $X;
			$arrayPoint[$cptPoint]["originalY"] = $Y;
			$cptPoint++;
			$Xp = $Rp*cos(deg2rad(90)-deg2rad($unit))+$centreX-25;
			$Yp = $Rp*sin(deg2rad(90)-deg2rad($unit))+$centreY;
			//calcul color for the text : come from the contact between rigth and left cell
			$contactReflexive = $arrayCellRelationship[$nameCell][$nameCell];
			//print("$nameCell : $contactReflexive<br />");
			$arrayParameter = colorContact($im,$contactReflexive);
			$colorText = $arrayParameter["color"];
			//orientation of the text
			$textAngle = 0;
			if($X>$centreX)
			{
				//bottom rigth
				if($Y>$centreY)
				{
					$textAngle = 360-(90-$unit);
				}
				//top rigth
				else
				{
					$textAngle = 360-(90-$unit);
				}
				//radius of text circle to drawn on
				$RpText = $Rp-40;
			}
			else
			{
				//bottom left
				if($Y>$centreY)
				{
					$textAngle = 90+$unit;
				}
				//top left
				else
				{
					$textAngle = 90+$unit;
				}
				//radius of text circle to drawn on
				$RpText = $Rp+70;
			}
			//lower left corner coordinate to display text
			$Xp = $RpText*cos(deg2rad(90)-deg2rad($unit))+$centreX;
			$Yp = $RpText*sin(deg2rad(90)-deg2rad($unit))+$centreY;
			//the font file has to be present in local
			imagettftext($im,36,$textAngle,$Xp,$Yp,$colorText,"./fonts/arial.ttf",$nameCell);
			$position[$nameCell]["X"] = $X;
			$position[$nameCell]["Y"] = $Y;
			$position[$nameCell]["angle"] = $unit;
			$unit+=$alpha;
		}
		foreach($arrayCellRelationship as $cellObject=>$arrayCellSubject)
		{
			foreach($arrayCellSubject as $cellSubject=>$contact)
			{
				$arrayCellRelationshipForSort["$cellObject:$cellSubject"] = $contact;
			}
			////////////////////////////
		}
		
		if($mode)
		{
			arsort($arrayCellRelationshipForSort);
		}
		else
		{
			asort($arrayCellRelationshipForSort);
		}
		foreach($arrayCellRelationshipForSort as $keyCellRelationship=>$contact)
		{
			$arrayKeyCellRelationship = explode(":",$keyCellRelationship);
			$cellObject = $arrayKeyCellRelationship[0];
			$cellSubject = $arrayKeyCellRelationship[1];
			$X = $position[$cellObject]["X"];
			$Y = $position[$cellObject]["Y"];
			$X2 = $position[$cellSubject]["X"];
			$Y2 = $position[$cellSubject]["Y"];
			$arrayCoordinates = array($X, $Y, $X2, $Y2);
			//special treatment for relationship for the same cell with itself
			if($cellObject==$cellSubject)
			{
				//do nothing
			}
			else
			{
				$arrayParameter = colorContact($im,$contact);
				$color = $arrayParameter["color"];
				$thickness = $arrayParameter["thickness"];
		//		print("$cellObject : $cellSubject = $contact / $thickness <br />");
				imagelinethick($im,$X,$Y,$X2,$Y2,$color,$thickness);
				//drawLine($im,$arrayCoordinates,$color,$thickness);
			}
		}
		//draw black points to mark cells positions
		foreach ($arrayPoint as $arrayCoordinate)
		{
			//draw clack circle
			$colorPoint = createColor($im,0,0,0);
			imagefilledellipse($im,$arrayCoordinate["originalX"],$arrayCoordinate["originalY"],10,10,$colorPoint);
		}
		//display the legend
		displayLegend($im,array($h-50,$h-230,$h+60,$h));
		//display the header for image image
		header("Content-type:image/png");
		//display the image as png
		imagepng($im);
		imagedestroy($im);
		return null;
	}
?>
<?
	include ("connection.php");
	//height of the image
	$height = 1500;
	//developmental stage wanted
	if(!empty($_GET["stage"]))
	{
		$idStage = $_GET["stage"];
	}
	else
	{
		print("<h2>Wrong developmental stage choosen</h2>");
	}
		//species chosen
	if(!empty($_GET["species"]))
	{
		$nameSpecies = $_GET["species"];
	}
	else
	{
		print("<h2>Wrong species choosen</h2>");
	}
	if(!empty($_GET["mode"]))
	{
		$mode = $_GET["mode"];
		if($mode==1)
		{
			$mode = true;
		}
		else
		{
			$mode = false;
		}
	}
	else
	{
		$mode = false;
	}

	//variable declaration
	//double associative array containing contact informations (key: cell object =>( key: cell subject => contact value))
	$arrayContact = array();
	//double associative array with formated cells names (no left and rigth) containing contact informations (key: cell object =>( key: cell subject => contact value))
	$arrayContactFinal = array();
	//select name of the stage
	$queryStageName = "SELECT \"NAME\" AS name
		FROM \"DEV_STAGE\"
		WHERE \"DEV_STAGE_ID\"=$idStage;";
	//select all neighboring relationships of cells in a developemental stage and contact between them
	$queryCellRelationship = "SELECT A1.\"NAME\" AS object, A2.\"NAME\" AS subject,
			\"CONTACT\" AS contact
		FROM \"NEIGHBOR\"
			JOIN \"ANAT_ENTITY\" A1 ON(A1.\"ANAT_ID\"=\"CELL_A\")
			JOIN \"ANAT_ENTITY\" A2 ON(A2.\"ANAT_ID\"=\"CELL_B\")
		WHERE \"CELL_A\" IN(
			SELECT \"ANAT_ID\"
			FROM \"ANAT_ENTITY\"
			WHERE \"DEV_STAGE_ID\"=$idStage
				AND \"SPECIES\"='$nameSpecies'
			)
			AND \"CELL_B\" IN(
			SELECT \"ANAT_ID\"
			FROM \"ANAT_ENTITY\"
			WHERE \"DEV_STAGE_ID\"=$idStage
				AND \"SPECIES\"='$nameSpecies'
			)
			AND \"CONTACT\">0;";
	
	
	//select name of the stage
	$resultStageName = pg_query($c,$queryStageName);
	$rowStageName = pg_fetch_array($resultStageName);
	$nameStage = $rowStageName["name"];
	//select all neighboring relationships of cells in a developemental stage and contact between them
	$resultCellRelationship = pg_query($c,$queryCellRelationship);
	//foreach neighboring relationship, calculate the contact between cells
	while($rowCellRelationship=pg_fetch_array($resultCellRelationship))
	{
		$cellObject = $rowCellRelationship["object"];
		$cellSubject = $rowCellRelationship["subject"];
		$arrayContact[$cellObject][$cellSubject] = $rowCellRelationship["contact"];
		$arrayContact[$cellSubject][$cellObject] = $rowCellRelationship["contact"];
	}
	
	foreach($arrayContact as $cellObject=>$arrayContactCellObject)
	{
		$cellObjectFormated = str_replace("*","",$cellObject);
		foreach($arrayContactCellObject as $cellSubject=>$contact)
		{
			$cellSubjectFormated = str_replace("*","",$cellSubject);
			$arrayContactFinal[$cellObjectFormated][$cellSubjectFormated] += $contact;
		}
	}
	
	//do the mean of the left and rigth part
	foreach($arrayContactFinal as $cellObject=>$arrayContactCellObject)
	{
		foreach($arrayContactCellObject as $cellSubject=>$contact)
		{
			$arrayContactFinal[$cellObject][$cellSubject] = $contact/2;
		}
	}
	//sort the array to display it properly
	$arrayContactFinalSorted = mySortByCellKey($arrayContactFinal);
	//display the image
	display_network($arrayContactFinalSorted,$height,$height,$mode);
?>
