// debug alerts through # 13:
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Behavior:
// 
// Ordinary PDB files display the molecular view immediately, then change
// the control panel and show the Introduction in the help panel.
// 
// ConSurf PDB files delay the molecular view (while echoing a "Processing"
// message in the middle of Jmol) while the header is processed. Then
// the ConSurf molecular view is show, the ConSurf control panel, and the
// ConSurf help panel.
// 
// If the PDB file contains "consurf" in its name, but lacks a ConSurf PiPE block,
// the default FG molecular view, control panel and Introduction help are shown,
// but after a delay for header processing.
// 
// If the PDB file is a ConSurf file, but lacks "consurf" in its filename,
// the display is correct, following a brief display of the default FG molecular
// view.
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// PDB file header processing mechanism (new in FG 0.995, for ConSurf):
// 
// 1. consurfMode and processHeaderBeforeMolView are initially
// false. (top.js)
// 
// 2. If the PDB filename contains "consurf",
// processHeaderBeforeMolView is set to true. (top.js)
// 
// 3. if (processHeaderBeforeMolView), the view1Spt does not render
// the molecular view, but echos a message to the middle of Jmol.
// (scripts.js)
// 
// 4. The PDB file header is obtained and split into pdbHeader and
// pipeBlock unconditionally. (msgcall.js)
// 
// 5. If pipeBlock is nonzero length, and contains
// "consurf_run_number", consurfMode is set to true. (pipe.js)
// 
// 6. Upon completion of header processing (msgcall.js, see comment
// 'startconsurf'), the molecular view is rendered (regardless of
// consurfMode), and the appropriate control panel and help are
// displayed.
// 
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

var collectMessages = false;
var messageStream = "";
var BadPdb = false;
var signedAccessErrorSuppressed = false;

//var messageMarkEndFirstView = "# end of firstview script";
//var messageMarkEndHeader    = "# end of pdbheader listing";
var messageMarkEndFirstView = "mark_end_firstview";
var messageMarkBeginHeader    = "mark_begin_show_pdbheader";
var messageMarkEndHeader    = "mark_end_pdbheader_listing";

var messageGetBlockMark = "GettingMessageBlock_";
var stateScript = "";
var showOrientation = "";

var pipeBlock = "";
var pdbHeader = ""

var line_end = "\n";

var consurfSpt = "";

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function showTextInWindow(text) // for debugging
{
		var messageWin = window.open("");
		with (messageWin.document)
		{
			writeln("<pre>\n" + text + "</pre>");
		}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function showMessagesInWindow()
{
	showTextInWindow(messageStream);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
function showMessageTopEscapedInWindow()
{
	var mesc = messageStream.substring(0,600);
	mesc = mesc.replace(/\n/g, "\\n\n");
	mesc = mesc.replace(/\r/g, "\\r\r");
	showTextInWindow(mesc);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

// for debugging
var msgCbackNo = 0;

// IMPORTANT: MULTIPLE CALLBACKS OCCUR BEFORE OTHERS HAVE RETURNED. THEREFORE,
// MULTIPLE CALLBACKS EXECUTE CONCURRENTLY, AND EXTERNAL VARIABLES BECOME
// CONFOUNDED. This is why I went to loadStructCallback() at Bob's advice.

function jmolMessageCallback(appletNumber, message0, p3, p4)
{
	msgCbackNo++;
	var thisCbkNo = msgCbackNo;

	// TO AVOID SAFARI CRASH
	var message = "" + message0;
	var mlower = message.toLowerCase();

//	if (message.indexOf("atoms selected") == -1)
//		alert("msgcall.js #1: entering jmolMessageCallback()\n" +
//			appletNumber + 
//			"\nthisCbkNo=" + thisCbkNo +
//			"\n" + message +
//			"\np3=" + p3 + "\np4=" + p4);

// DEBUGGING
	if (false) // false when not debugging
	{
		if (message.indexOf("atoms selected") == -1
			&& message.indexOf("Script completed") == -1)

			alert("msgcall.js #1a: received message\n" + message);
	}
	
	if (false)
	{
		if (mlower.indexOf("pdbheader_listing") != -1
			|| mlower.indexOf("script") != -1
			|| mlower.indexOf("error") != -1)

			alert("msgcall.js #1b:\n" + message);
	}

//	alert("msgcall.js #11b: BadPdb=" + BadPdb +
//		"\nthisCbkNo=" + thisCbkNo);

// END DEBUGGING

	// ALERT ON ERRORS
// THIS CODE DOES NOT WORK DUE TO CONCURRENT ASYNCHRONOUS CALLBACKS
//	if (!BadPdb) // once true, always true!
//	{
//		BadPdb = (mlower.indexOf("filenotfoundexception") != -1);
//		if (BadPdb) // we just found out, so
//		{
////			showHelp('makeTroubleHelp()');
////			showHelp('makeBadPDBFileHelp()');

//			alert("ERROR: The specified PDB file,\n" + top.pdbToLoad +
//				"\n does not exist or is not accessible\n" +
//				"(FileNotFoundException).\n" +
//				"There is no molecule to display.\n" +
//				"See the troubleshooting help at left.\n" +
//				"Please check whether " + validPDBId + " has status HPUB\n" +
//				"(on hold, to be released upon publication).");

////				"Click OK, then please close this window.");
//		}		
//	}

//	alert("msgcall.js #11a: BadPdb=" + BadPdb);

//	if (BadPdb)
//	{
//		alert("msgcall.js #11 (return next): BadPdb=" + BadPdb +
//			"\nthisCbkNo=" + thisCbkNo);
//		return; // do nothing else, we're done!
//	}

	// REPORT UNEXPECTED JMOL ERRORS

	var reportError = false;
	if ((mlower.indexOf("error")           != -1 ||
		mlower.indexOf("exception") != -1 ||
		mlower.indexOf("permission") != -1 ||
		mlower.indexOf("command expected") != -1) &&
		message.substring(0, 7) != "HEADER ") // don't report ESTIMATED ERROR ...
			reportError = true;

	// suppress one error if using signed applet
	if (message.indexOf("AccessControlException") != -1 && usingSignedApplet)
	{
		if (!signedAccessErrorSuppressed)
		{
//			reportError = false; // suppress error once
			signedAccessErrorReported = true;		
		}
	}

	// suppress filenotfoundexception which is handled by jmolLoadStructCallback().
	if (mlower.indexOf("filenotfoundexception") != -1)
		reportError = false;

	// don't report jmol bug isspinning TEMPORARY pending jmol fix @@
//	if (reportError)
//	{
//		if (mlower.indexOf("isspinning")  != -1)
//			reportError = false;
//	}

//	alert("msgcall.js #12: reportError = " + reportError +
//			"\nthisCbkNo=" + thisCbkNo);

	if (reportError)	
	{
		var jcmd = message;
		var cstart = "select (";
		var isp = jcmd.indexOf(cstart);
		jcmd = jcmd.substring(isp + cstart.length);
		jcmd = jcmd.substring(0, jcmd.indexOf(")"));

		// "see halos easily" with a bad "find" command issues "select"
		// without (), making isp == -1.

		if (match(helpPanel, "find") && isp != -1)
		{
			var emsg = "Error: Jmol does not know how to find:\n\""
				+ jcmd +
				"\"\nPlease reword what you want to find.\n";
			if (jcmd.indexOf(" ") != -1)
				emsg += "(Please remember to put commas between terms.)";

			alert(emsg);

//			"\n currentView is \"" + currentView + "\"" +
//			"\n helpPanel is \"" + helpPanel + "\"");
		}
		else if (!match(helpPanel, "find"))
			alert("jmolMessageCallback() reports #" + thisCbkNo +
			":\n" + message);

		// else no alert: bad "find" command and "see halos easily"

	}

	// ---- END: REPORT UNEXPECTED ERRORS ----

	// START FETCH PDBHEADER
	if (mlower.indexOf(messageMarkEndFirstView) != -1)
		setTimeout("beginFetchPDBHeader()", 250); // let a few more messages pass

	// COLLECT MESSAGES
	if (collectMessages)
		messageStream += message + "\n";

	// FINISH PDBHEADER COLLECTION, PROCESS PDBHEADER
	if (mlower.indexOf(messageMarkEndHeader) != -1)
		setTimeout("processPDBHeader()", 250);

	// START GET MESSAGE BLOCK
	if (message.indexOf("begin" + messageGetBlockMark) != -1)
	{
//		alert("msgcall.js #10:\n" + m
		messageStream = "";
		collectMessages = true;
	}

	// END GET MESSAGE BLOCK
	var imm;
	if ((imm = message.indexOf("end" + messageGetBlockMark)) != -1)
	{
		collectMessages = false;

		// get index of message block
		var immu = mlower.indexOf("_", imm);
		var immu2 = mlower.indexOf("_", immu + 1);
		var imms = mlower.substring(immu + 1, immu2);
//		alert("msgcall.js #8: imb string = |" + imms + "|");
		var imb = parseInt(imms);

		// trim off end of block mark
		var illin = messageStream.lastIndexOf("\n", messageStream.length - 2);
		messageStream = messageStream.substring(0, illin + 1);

		// save message block
		messageBlock[imb] = messageStream;
		messageStream = "";
	}
}

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function beginFetchPDBHeader()
{
//	alert("msgcall.js #3: beginFetchPDBHeader()");

	collectMessages = true;
//	alert("msgcall.js #6: getPDBFileHeaderSpt:\n" + getPDBFileHeaderSpt);
	unchangedScriptToJmol(makeGetPDBFileHeaderSpt());
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function processPDBHeader()
{
	collectMessages = false;
	getPIPEBlock();
	if (telAvivMode) // pepsurfMode is setup in pipe.js setup_pepsurf()
	{
		controlPanel = "consurf";
		initConsurf(); // defines some external variables
		writeConsurfControls(); // startconsurf
		consurfSpt = makeConsurfViewSpt(); // nothing is conditional here
		if (consurfMode || selectonMode || epitopiaMode) //@@STON
			currentView = "makeConsurfViewSpt()";
		else // pepsurfMode
			currentView = "make_pepsurf_display_spt()";
		var csView = makeHideMiddleEchoSpt() + consurfSpt;
		doMolViewSpt(csView);
//		showTextInWindow(csView);
		showHelp("makeConsurfHelp()");
		if (consurfMode || selectonMode || epitopiaMode) //@@STON
			helpPanel = "consurf";
		else // pepsurfMode
			helpPanel = "pepsurf";
	}
	else if (pipeBlock.length > 0)
		alert("ERROR: consurfMode, pepsurfMode, selectonMode all\nfalse but PiPE Block is present.");
	else
	{
		if (processHeaderBeforeMolView)
			doMolViewSpt(makeHideMiddleEchoSpt() + view1RenderSpt);
		writeFGControls();
//		setTimeout("returnToIntro()", 250);
		returnToIntro();
		setTimeout("slideit()", 5000);
	}

//	alert("msgcall.js #7: pipeBlock.length = " + pipeBlock.length);
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function getPIPEBlock() // adapted from shared/hcquery.js in PE.
{
	var rawheader = messageStream;

//		showTextInWindow("msgcall.js #5: rawheader:\n" +
//			rawheader + "========");

	var elb = line_end + "!"; // End Line Bang

	// Find first PIPE line (first line beginning "!")
	var begin_pipe; // index of first line beginning "!"
	if (rawheader.charAt(0) == "!")
		begin_pipe = 0;
	else
		begin_pipe = rawheader.indexOf(elb);
	if (begin_pipe > 0)
		begin_pipe += line_end.length; // move index forward to "!"

	// Find last PIPE line (last line beginning "!")
	var end_pipe = -1; // index of END of last line beginning "!"
	if (begin_pipe != -1)
	{
		end_pipe = rawheader.lastIndexOf(elb);
//		alert("hcquery.js #22: begin_pipe = " + begin_pipe + "\n" +
//			"end_pipe = " + end_pipe + "\n");

		// fails if there is only one PIPE line and it is the first line
		if (end_pipe == -1)
		{
			alert("Fatal error: cannot find end_pipe.");
			return; // leaving pipeBlock empty
		}

		// end_pipe stands at BEGINNING of last line.
		// Move end_pipe forward to END of last PIPE line
		end_pipe = rawheader.indexOf(line_end, end_pipe + elb.length);

		// Move end_pipe forward to include trailing \r\n, or isMac, \r
		// last PIPE line is never the last line in the file (always followed at
		// least by ATOM lines).
		end_pipe += line_end.length;
	}

//		alert("msgcall.js #2: begin_pipe = " + begin_pipe + "\n" +
//			"end_pipe = " + end_pipe + "\n");

	// Separate Original Header from PiPE Block
	if (begin_pipe != -1)
	{
		if (begin_pipe > 0)
			pdbHeader += rawheader.substring(0, begin_pipe);
		pdbHeader += rawheader.substring(end_pipe);

		pipeBlock = rawheader.substring(begin_pipe, end_pipe);

//		showTextInWindow("msgcall.js #4:\n" +
//			pdbHeader + "======================\n" + pipeBlock + "========");
	}
	else // no PIPE
		pdbHeader = rawheader;

	if (pipeBlock.length > 0)
		top.setup_pipe();
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This plan is designed to permit a series of getMessageBlock() requests,
// allowing
// the Nth request to be made before the (N-1)th request is completed.
// Script queuing in Jmol ensures that each request is satisfied in order.
//
// Example, using state:
//
// requestMessageBlock("show state;")
//   returns an array index imb, after reserving the imb array members
//     messageBlockInUse[imb] = true;
//     and blanking messageBlock[imb] = "";
//   and sending a message-bracketed script to Jmol.
//
// messageCallback() notes start of the format
//   message beginGettingMessageBlock_0_
//   collects messages, notes endGettingMessageBlock_0_
//   places message block in messageBlock[0].
//
// At intervals, the requester (saying one moment please) looks for a 
// nonblank messageBlock[imb]. On finding it, it saves it, calls
// clearMessageBlock[imb], and takes the next step.

var messageBlockInUse = new Array();
messageBlockInUse[0] = false;
var messageBlock = new Array();

function requestMessageBlock(showCommand)
{
	// N.B.: showCommand must not change the molecular view.
	
	var imb = 0;
	while(messageBlockInUse[imb])
		imb++;
	messageBlockInUse[imb] = true;
	messageBlock[imb] = "";

	var spt = "message begin" + messageGetBlockMark + imb + "_;\n" +
		showCommand + "\n" +
		"message end" + messageGetBlockMark + imb + "_;\n";

//	alert("msgcall.js #9: sending script:\n" + spt);

	unchangedScriptToJmol(spt);		
	return imb;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function clearMessageBlock(imb)
{
	messageBlock[imb] = "";
	messageBlockInUse[imb] = false;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// new HPUB detection code in loadStructCallback().

function jmolLoadStructCallback(rp1, rp2, rp3, rp4, rp5)
{
	var p1 = "" + rp1;
	var p2 = "" + rp2;
	var p3 = "" + rp3;
	var p4 = "" + rp4;
	var p5 = "" + rp5;
//	var p6 = "" + rp6; // undefined
//	var p7 = "" + rp7; // undefined

//	alert("msgcall.js #13 jmolLoadStructCallback():\n" +
//		"p1 = " + p1 + "\n" +
//		"p2 = " + p2 + "\n" +
//		"p3 = " + p3 + "\n" +
//		"p4 = " + p4 + "\n" +
//		"p5 = " + p5 + "\n");

// Not sure if this timeout is doing any good. Reloading the page for an HPUB
// shows the NoPDB messge only intermittantly, even with the timeout.

	if (p2 == "0" // Safari
		|| p2 == "null" ) // Firefox
	{
		setTimeout("announceNoPDB()", 500);
	}
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function announceNoPDB()
{
	// This destroys the ability of the "Can't see the molecule?" help
	// to display in the helpDiv.
//	document.getElementById('leftDiv').innerHTML = makeBadPDBFileHelp();

	showHelp('makeBadPDBFileHelp()');

	document.getElementById('controlsDiv').innerHTML =
"<center><br><big><b>Oops ...</b></big></center>";
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

