#!/cygdrive/c/strawberry/perl/bin/perl -w

# Need to specify the full path of Perl above, e.g. for Windows something like
#!C:\\Perl32\\bin\\perl -w

use strict;

# Set this to 1 to work around IIS 6 craziness
my $iis6_mode = 0;


# IIS 6: for some reason, IIS runs this script with the working directory set to the Greenstone
#   directory rather than the cgi-bin directory, causing lots of stuff to fail
if ($iis6_mode)
{
    # Change into cgi-bin directory
    chdir("cgi-bin");
}


# We use require and an eval here (instead of "use") to catch any errors loading the module (for IIS)
eval("require \"gsdlCGI.pm\"");
if ($@)
{
    print STDOUT "Content-type:text/plain\n\n";
    print STDOUT "ERROR: $@\n";
    exit 0;
}

sub generate_html_form
{
	my($isGSDL2,$site,$collect,$cl) = @_;
	
	# first generate the document frames
	# then generate the classifier browsing frames.
	
	my $html_form = <<EOT;
	<html>
		<head>
			<title>HTML To Expeditee Frames</title>
			<base href=".."/>
			
			<link type="text/css" href="ext/html-to-expeditee/jquery/css/le-frog/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
			<script type="text/javascript" src="ext/html-to-expeditee/jquery/js/jquery-1.6.2.min.js"></script>
			<script type="text/javascript" src="ext/html-to-expeditee/jquery/js/jquery-ui-1.8.16.custom.min.js"></script>
			<script type="text/javascript" src="ext/html-to-expeditee/js/gsajax-min.js"></script>
			<script type="text/javascript" src="ext/html-to-expeditee/js/html-to-expeditee.js"></script>
		</head>
		<body>
			<form class="ui-widget">
				Convert the collection <input type="text" class="ui-corner-all" style="padding: 4px;" name="collect" value="$collect" id="collect" /> to Expeditee frames by traversing the classifier <input type="text" class="ui-corner-all" style="padding: 4px;" name="cl" value="$cl" id="cl" />

				<input value="$site" name="site" id="site" type="hidden">
        
				<p>
					<input type="checkbox" id="checkBoxBrowsing" name="generate_browsing" value="generate_browsing">Generate Collection Space<br/>
				</p>
		
				<p style="font-weight: bold;">Extra Expeditee Frame Output Options:</p>
				<input type="checkbox" id="checkBoxFont" name="compute_font" value="compute_font">Compute Font<br/>
				<input type="checkbox" id="checkBoxWidth" name="compute_width" value="compute_width">Compute Width<br/>
		
				<p><input value="Go" id="go" class="ui-button ui-widget ui-state-default ui-corner-all" type="submit"></p>
				</form>
				
				<script type="text/javascript">
					var collect;
					var site;
					var cl;
					var gs2;
					
					var docOIDs = [];
					var clPages = [];
					
					var hashMapDocFrames = new Array();
					
					var numDocOIDs = 0;
					var numClPages = 0;
					
					var currDocFrameNum;
					var currClFrameNum;
					
					var compute_font = false;
					var compute_width = false;
					var generate_browsing = false;	//generate a matching collection space frameset
					
					\$(function(){
						
						\$('#progress').progressbar();
						
						\$('#go').button().click(function(){
							
							site = document.getElementById("site").value;
							
							collect = document.getElementById("collect").value;
							
							if(collect.match(/^\\s*\$/)){
								alert("No collection specified");
								return false;
							}
							
							cl = document.getElementById("cl").value;
							if(cl.match(/^\\s*\$/)){
								alert("No classifier specified");
								return false;
							}
							
							compute_font = document.getElementById("checkBoxFont").checked;
							compute_width = document.getElementById("checkBoxWidth").checked;
							
							generate_browsing = document.getElementById("checkBoxBrowsing").checked;
							
							gs2=$isGSDL2;
							
							var url;
							
							/*obtain url for classifier/browse page and grab all links (doc and CL links) from this page.*/
							if(gs2){
								url = "library.cgi";
								url += "?c="+collect +"&a=d&cl=" + cl;
							}else{
								url = "library";
								url += "?c="+collect +"&a=b&rt=s&s=ClassifierBrowse&cl=" + cl;\
								url += "&excerptid=gs_content";
							}
							
							docOIDs = [];
							clPages = [];
							
							var outstandingURLs = [];
							var visitedURLs = {};
							
							outstandingURLs.push(url);
							visitedURLs[url] = 1;
							
							while(outstandingURLs.length > 0){
								url = outstandingURLs.shift();
								
								var clHtml = urlGetSync(url);
								
								var workingTrav = document.getElementById("workingTraverse");
								workingTrav.innerHTML = clHtml;
								
								var aElems = workingTrav.getElementsByTagName("a");
								
								/* any links with (document|browse)=> outstandingURLS */
								/* any links with (document|browse)/CL[0-9]/[0-9] => clPages */
								/* any links with (document) => docOIDs */
								
								var actionRE = new RegExp("(\\\\/)(?:document|browse)(\\\\/)");
								var clRE     = new RegExp("(\\\\/)browse\\\\/" + cl + "(\\\\/\\\\d+)+(\$)");
								var docRE    = new RegExp("(?:\\\\/)document\\\\/(.*?)(?:\$)");
								
								for(var i = 0; i < aElems.length; i++){
									var aElem = aElems[i];
									var href = aElem.href;
									
									if(href && href.match(actionRE)){
										if(href.match(clRE)){
											if(!visitedURLs[href]){
												console.log("found a new CL line: " + href);
												outstandingURLs.push(href);
												visitedURLs[href] = 1;
												clPages.push(href);
											}
										}else if(href.match(docRE)){
											if(!visitedURLs[href]){
												var docMatch = docRE.exec(href);
												var docOID = docMatch[1];
												
												console.log("found a new doc line: " + docOID);
												visitedURLs[href] = 1;
												docOIDs.push(docOID);
											}
										}
									}
								}
							}
							
							numDocOIDs = docOIDs.length;
							numClPages = clPages.length;
							var iframe = document.getElementById('iframe');
							
							startProcessing(iframe);		//Process documents
														
							return false;
						});
						
					});
					
					function startProcessing(iframe){
						
						var docOID = docOIDs.shift();
						
						iframe.src = getDocumentUrl(docOID);
						
						var progressbar = document.getElementById('progressbar');
						progressbar.style.display = 'block';					
					}
					
										
					function pageLoaded(){
						var iframe = document.getElementById("iframe");
						
						if(iframe.src){
							
							if(iframe.style.display != 'block'){
								iframe.height = '90%';
								iframe.style.display = 'block';
							}
							
							var iframeDoc;
							
							if(iframe.contentDocument){ /* FF and Chrome */
								iframeDoc = iframe.contentDocument;
							}else if(iframe.contentWindow){	/* IE */
								iframeDoc = iframe.contentWindow.document;
							}
						
							/*Check url - if it's a doc Url, call "writeDocument", otherwise call "writeClPage"*/
							var clRE = new RegExp("(\\\\/)browse\\\\/" + cl + "(\\\\/\\\\d+)+(\$)");
							
							
							if(iframe.src.match(clRE)){
								writeClPage(iframe,iframeDoc);
							}else{
								writeDocument(iframe,iframeDoc);
							}
						}
					}
					
					function writeDocument(iframe,iframeDoc){
						
						var xmlUrl = iframe.src + "&o=xml";
						
						var iter = (numDocOIDs - docOIDs.length);
						var progressPercent = iter/numDocOIDs * 100;
						
						var frameNum = getMetadata(xmlUrl,'frameID');
						
						if(frameNum == null){
							frameNum = iter;
						}
						
						//Add docOID and matching frame number to an associative array for later use.
						hashMapDocFrames[docOID] = frameNum;
						
						\$(function(){
							\$('#progressbar').progressbar({ value: progressPercent });
						});
						
						var gsContent = iframeDoc.getElementById("gs_content");
						
						var assocElem = iframeDoc.getElementById("assocfilepath");
						
						var assocElem = iframeDoc.getElementById('assocfilepath');
						var assoc = null;
						
						if(assocElem === undefined || assocElem === null){
							assoc = getMetadata(xmlUrl,'assocfilepath');
						}
						
						var expFrameTree = htmlToExpeditee(gsContent,compute_font,compute_width);
						
						var expFrame = JSON.stringify(expFrameTree);
						//console.log(expFrame);
						
						var url = "cgi-bin/html-to-expeditee.pl";
						var params = "c=" + collect;
						
						if(site.match(/\\w/)){
							params += "&site=" + site;
						}
						
						params += "&a=generate-frame&fn=" + frameNum;
						params += "&json=" + escape(expFrame);
						
						//Add an assocfilepath but only if it is defined
						if(assoc !== null){
							params += "&assoc=" + assoc;
						}
						
						params += "&compute-font=" + compute_font;
												
						params += "&page-type=" + "document";
											
						
						var clHtml = urlPostSync(url,params);
						
						if(!clHtml.match(/html-to-expeditee saved frame/)){
							alert("ERROR PROCESSING URL: " + url);
						}
						
						if(docOIDs.length > 0){
							var docOID = docOIDs.shift();
							iframe.src = getDocumentUrl(docOID);
							
						}else{
							//start writing CL pages.
							if(generate_browsing){
								numClPages = clPages.length;
							
								var url = clPages.shift();
								iframe.src = url;
								writeClPage(iframe,iframeDoc);
							}else{
								//We are finished
								finish(iframe);
							}
						}	
					}
					
					function getDocumentUrl(docOID){
						var url;
						
						if(gs2){
							url = "library.cgi";
						}else{
							url = "library";
						}
						
						url += "?c=" + collect + "&a=d&d=" + docOID;
										
						url += "&p.showAssocFilePath = 1";
						
						return url;
					}
					
					function writeClPage(iframe,iframeDoc){
						
						var frameNum = numClPages - clPages.length;
						var progressPercent = frameNum / numClPages * 100;
						
						\$(function(){
							\$('#progressbar').progressbar({ value: progressPercent });
						});
						
						var gsContent = iframeDoc.getElementById("gs_content");
						var gsContentChildren = gsContent.getElementsByTagName('*');
						
						var docRE    = new RegExp("(?:\\\\/)document\\\\/(.*?)(?:\$)");
						
						//get rid of rectangles around nodes.
						for(var i = 0; i < gsContentChildren.length; i++){
							var child = gsContentChildren[i];
							
							if(child.tagName !== "IMG"){
								child.setAttribute('rect','norect');
							}
							
							if(child.tagName === "A"){
								var aElem = child;
								var aElemSrc = aElem.href;
								
								//if aElemSrc is a document url, then extract docOID then access hash map and get matching frame number.
								if(aElemSrc.match(docRE)){
									var docMatch = docRE.exec(aElemSrc);
									var docOID = docMatch[1];
									console.log("*** " + docOID);
									var frameNum = hashMapDocFrames[docOID];
									var aElemChildren = aElem.getElementsByTagName('*');
									
									for(var j = 0; j < aElemChildren.length; j++){
										var aElemChild = aElemChildren[j];
										var frameName = collect + frameNum;
										//console.log("*** " + frameName);
										//aElemChild.setAttribute("link",frameName);
										//console.log(aElemChild.link);
									}
									
								}else{
									//TODO: Check if the link is a CL link.
									//TODO: Make a hashmap for storing CL page frame numbers?
								}
							}
						}
						
						//add link attribute to children nodes of <a> elements.
						
						
						//TODO: Need to change htmlToExpeditee code to account for links
						
						
						var expFrameTree = htmlToExpeditee(gsContent);
						var expFrame = JSON.stringify(expFrameTree);
						//console.log(expFrame);
						
						var url = "cgi-bin/html-to-expeditee.pl";
						var params = "c=" + collect;
						
						if(site.match(/\\w/)){
							params += "&site=" + site;
						}
						
						params += "&cl=" + cl;
						params += "&a=generate-frame&fn=" + frameNum;
						params += "&json=" + escape(expFrame);
						params += "&page-type=" + "clPage";
						
						var clHtml = urlPostSync(url,params);
						
						if(!clHtml.match(/html-to-expeditee saved frame/)){
							alert("Error processing url: " + url);
						}
						
						if(clPages.length > 0){
							var clPage = clPages.shift();
							iframe.src = clPage;
						}else{
							finish(iframe);
						}
					}
					
					function finish(iframe){
						var progressbar = document.getElementById("progressbar");
						progressbar.style.display = "none";
						
						iframe.style.display = "none";
						delete iframe.src;
					}
					
					/**
					* This method is used at this stage to retrieve assocfilepath and
					* frame number metadata values from the document's xml.
					**/
					function getMetadata(xmlUrl,nameValue){
						var metadata = null;
						
						\$.ajax({
							type: "GET",
							async: false,
							url: xmlUrl,
							dataType: "xml",
							success: function(xml){
								\$(xml).find('metadata').each(function(){
									var name = \$(this).attr('name');
									
									if(name === nameValue){
										if(metadata === null){
											metadata = \$(this).text();
										}
									}
								});
							}
						});
						
						return metadata;
					}
					
				</script>
				
				<div id="progressbar" width="100%" style="display: none; margin: 10px; height: 10px;"></div>
				
				<div id="workingTraverse" style="display: none"></div>
				
				<hr style="margin: 10px;">
				
				<iframe width="100%" id="iframe" style="display:none;" onload="pageLoaded()"></iframe>
	</body>	
</html>			
EOT

	print "Content-type:text/html\n\n";
	print $html_form;
}

sub main
{
	my $gsdl_cgi = new gsdlCGI();
	
	#Load GS modules
	$gsdl_cgi->setup_gsdl();
	
	my $gsdlhome = $ENV{'GSDLHOME'};
	$gsdl_cgi->checked_chdir($gsdlhome);
	
	#TODO: Refactor so we only need to use HtmlToExpediteeAction
	require cgiactions::HtmlToExpediteeAction;
	require cgiactions::CollectionSpaceAction;
	
	$gsdl_cgi->parse_cgi_args();
	$gsdl_cgi->{'xml'} = 0;
	
	my $fn = $gsdl_cgi->clean_param("fn");
	
	if(defined $fn){
		#page_type can have two values: "document" or "clPage"
		my $page_type = $gsdl_cgi->clean_param("page-type");
		
		if(defined $page_type){
			my $action;
			
			if($page_type eq "document"){
				$action = new HtmlToExpediteeAction($gsdl_cgi,$iis6_mode);
			}elsif($page_type eq "clPage"){
				$action = new CollectionSpaceAction($gsdl_cgi,$iis6_mode);
			}else{
				$gsdl_cgi->generate_error("Invalid page type specified. Must be 'document' or 'clPage'");
			}
			
			$action->do_action();
		}else{
			$gsdl_cgi->generate_error("No page type specified. Must be 'document' or 'clPage'");
		}
		
	}else{
		# generate html form
		my $collect = $gsdl_cgi->clean_param("collect");
		my $cl = $gsdl_cgi->clean_param("cl");
		
		#Establish collect_dir using defining 'site' along the way if GS3
		my $site = undef;
		my $isGSDL2 = undef;
		
		if($gsdl_cgi->greenstone_version() == 2){
			$isGSDL2 = 1;
		}else{
			$isGSDL2 = 0;
			
			#GS3 (and possible future versions) make use of 'site'
			$site = $gsdl_cgi->clean_param("site");
			
			if(!defined $site){
				$gsdl_cgi->generate_error("No site specified.");
			}	
		}
		
		generate_html_form($isGSDL2,$site,$collect,$cl);
	}
}

&main();