/*  options.js - option handling for GET parameters (of the form URL?key1=val1&key2=val2)
 *  top.options.handle() will run the appropriate function in top.options.handlers
 *  In this instance it will call top.options.handlers['key1']('val1') 
 *  then top.options.handlers['key2']('val2')
 */
top.options={};
top.options.handlers={};
top.options.bookMap={};

/*  Retry calling 'f' with no arguments upto 'tries' times
 *  tries=0 is equivalent to f(). There is a .25 second delay between calls
 *  and may run in a different thread (effectively). Thus you should only try this at the
 *  top level (top.options.handle is 'retry'd)
 */
function retry(f,tries){
    try{
	return f();
    }catch (e){
	if(tries==0){
	    throw e;
	}else{
	    setTimeout(function(){return retry(f,tries-1);},500);
	}
    }
}

/* Utility to wrap functions in a retry
 */
function retryable(f){
    return function(){
	return retry(f,100);
    };
}

/* Calls each function in args with no arguments.
 * There is a 100 Ms delay between calls.
 * The structure here is a little unusual but it means
 * that sequenced functions will be called in order while
 * individual components may fail.
 * This cannot be achieved with the more natural style of
 * a retry inside a for loop. 
 * So continuation passing style is used.
 */
function _sequence(args){
    var n=0;
    var f;
    f =retryable(
      function(){
        if(n>=args.length){
          return;
        }
        args[n]();
        n++;
        setTimeout(f,100);
      });
    return f;
}

/* Convenience wrapper for _sequence
 */
function sequence(){
    _sequence(arguments)();
}

/*  Here be Dragons! (this is the 'main' function)
 *  HandleOpts extracts key=value pairs from the URL and feeds them
 *  into the appropriate handlers based on the name of the key
 */
function handleOpts(){
    var args=top.location.search.split('?');
    if(!args || args.length<2)
	return;
    var Pairs = args[1].split('&');
    var p;
    for (i in Pairs){
	p=Pairs[i].split('=');
	fn=top.options.handlers[p[0]]
	if(fn){
	    fn(decodeURIComponent(p[1]));
	}
    }
}

/* looks up and sets the Name=>id mapping for the book with 'id' as webhelp's internal index
 */
function setBookName(id){
	if(id){
		top.options.bookMap[top.options.getBookName(id).toLowerCase()]=id;
	}
}

function getRoots(){
	return (top.options.roots || top.window.frames[0].getItemByBook)(top.document.body);
}
function buildBookMap(){
	if(!top.options.bookMapBuilt){
		sequence(top.options.showToc,top.options.showToc,
			function () { 
				roots=top.options.roots();
				if(roots && roots.length>0){
					for (i = 0;i<roots.length;i++){
						setBookName(parseInt(roots[i].id.slice(2)));
					}
					top.options.bookMapBuilt=roots;
				}else{
					throw "No Roots";
				}
			});
	}
}

/*  See whiform.htm or install.sh
 *  for the definition of indexLookup
 */
function indexHandler (term){
    top.options.indexLookup(term);
}

/*  A potentially useful handler for those who want to link into deeper books.
 *  Have to view 'onclick' property for book and 'insertItems(x,y)' means you 
 *  should link to ?_contents=x-y
 */
function _contentsHandler (term){
    var args=term.split('-');
    top.options.showBook(parseInt(args[0]),parseInt(args[1]));
}
/*  Uses bookMap to lookup a top-level book by name
 */
function displayBook(){
    	var term=top.options.contentsTerm
	if(!top.options.bookMapBuilt){
		buildBookMap();
		throw "No Bookmap";
	}
    	if(term){
      	term=top.options.bookMap[term];
      		if(term){
	 		var num = top.options.bookNum(term);
	      		if(num){
	      			top.options.showBook(term,num);
			}
		}
    	}
}

/*  This handler has complex flow due to the 'showToc' function
 *  being responsible for loading code required in buildBookMap
 *  and displayBook. The sequence function ensures the functions
 *  are called in order and can be retried.
 */
function contentsHandler(term){
    top.options.contentsTerm=term.toLowerCase();
    sequence((top.options.showToc=(top.options.showToc || top.window.frames[0].showToc)),
	     buildBookMap,
	     displayBook);
}

function getFrameDoc(id){
	if(window.navigator.userAgent.indexOf('MSIE')!=-1){
		return window.frames[id].document;
	}else{
		return window.document.getElementById(id).contentDocument;
	}
}

/* 
 * Adds the logo w/ specified url to the far right of the toolbar (top right corner)
 */

function addLogoImg(logoSrc){
    var links = getFrameDoc('toolbar').links;
    var link = links[links.length-1];
    var tr = link.parentNode.parentNode;
    var td=tr.insertCell(tr.cells.length-1);
    td.innerHTML='<a href="tgc.htm" id="logoLink" target="_top"><img border="0" height="19" src="'+encodeURI(logoSrc)+'">';
    link.href=top.document.location;
}

/* 
 * Makes the logo (added w/ adLogoImg) link to the specified URL (defaults to eTG menu)
 */
function setLogoHref(logoHref,dontRetry){
    var doc = getFrameDoc('toolbar');
    var l = doc.getElementById('logoLink');
    if (!l){
	setTimeout(function(){setLogoHref(logoHref,true);},500);
    }else{
	l.href=encodeURI(logoHref);
    }
}

/*
 *  Set the handlers
 */
top.options.handle=handleOpts;
top.options.handlers.index=indexHandler;
top.options.handlers._contents=_contentsHandler;
top.options.handlers.contents=contentsHandler;
top.options.handlers.logo=addLogoImg;
top.options.handlers.link=setLogoHref;

//set the handler to run once everything else has loaded.
setTimeout(retryable(top.options.handle),2900);

