// Seamark Ajax client
// This depends on the Yahoo! YUI Ajax library.  It's assumed that library is loaded by whoever includes this file.

YAHOO.namespace("siderean.panels");

var showLogger = false;   // set to true to show YAHOO logger
function initSeamarkAjaxClient() {
  YAHOO.siderean.panels.manager = new YAHOO.widget.OverlayManager();
  if (showLogger) {
    var logReader = new YAHOO.widget.LogReader(null, {newestOnTop:false});
    logReader.setTitle("Seamark Ajax Log");
  }
}


////////////////////////////////////
// Cross-browser DOM compatibility hacks and extensions
function setInnerHTML(element, html) {
  try {
    element.innerHTML = html;
  }
  catch (e) {
    // IE fails unless we wrap the string in another element.
    var wrappingDiv = document.createElement('div');
    wrappingDiv.innerHTML = html;
    if (element.firstChild) {
      element.removeChild(element.firstChild);
    }
    element.appendChild(wrappingDiv);
  }
}


/////////////////////////////////////
// SeamarkCommandInfo - MetaData associated with a SeamarkRequest, such as the 
// DOM destination of the result.
function SeamarkCommandInfo(destinationId, extraInfo) {
  var msg = "Creating SeamarkCommandCommandInfo, destId = " + destinationId + "\nextraInfo = " + extraInfo;
  //YAHOO.log(msg);
  //alert(msg);
  this.destinationId  = destinationId;
  this.extraInfo = extraInfo;
}

/////////////////////////////////////
// SessionInfo, supplied with stateles ("one-off") commands
function SeamarkSessionInfo(scriptName, soapURL, modelURI, user, pass) {
  var msg = "Creating SessionInfo, scriptName = " + scriptName + "\nsoapURL = " + soapURL + "\nmodelURI = " + modelURI + "\nxrbr = " + xrbr + "\nrenderStyle = " + renderStyle + "\nengineStyle = " + engineStyle;
  //alert(msg);
  // HACK: dummy xrbr just to make QueryState initialization happy
  var xrbr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xrbr:query xmlns:xrbr=\"http://www.siderean.com/2006/02/xrbr/\" item-type=\"NOTYPE\"><xrbr:facets><xrbr:facet name=\"NONAME\" predicate=\"NOPREDICATE\"><xrbr:hint/></xrbr:facet></xrbr:facets></xrbr:query>";
  // For now, hardcode renderStyle and engineStyle
  var renderStyle = "enterprise";
  var engineStyle = "jsp";

  this.scriptName = scriptName;
  this.soapURL = soapURL;
  this.modelURI = modelURI;
  this.xrbr = xrbr;
  this.renderStyle = renderStyle;
  this.engineStyle = engineStyle;
  this.user = user;
  this.pass = pass;
}

/////////////////////////////////////
// SeamarkRequest - Ajax request sent to Seamark Ajax Listener 
function SeamarkRequest(commandName, sessionInfo, commandInfo, commandArguments) {
  this.commandName = commandName;
  this.sessionInfo = sessionInfo;
  this.commandInfo = commandInfo;
  this.commandArguments = commandArguments;
}

SeamarkRequest.prototype.renderAsXML = function() {
  var q = "<seamarkRequest>\n" +
                "  <sessionId>" + this.sessionId + "</sessionId>\n" +
		"  <command>" + this.commandName + "</command>\n" +
                "  <sessionInfo>\n" +
                "     <soapURL>" + this.sessionInfo.soapURL + "</soapURL>\n" + 
                "     <scriptName>" + this.sessionInfo.scriptName + "</scriptName>\n" + 
                "     <modelURI>" + this.sessionInfo.modelURI + "</modelURI>\n" + 
                "     <xrbr><![CDATA[" + this.sessionInfo.xrbr + "]]></xrbr>\n" + 
                "     <renderStyle>" + this.sessionInfo.renderStyle + "</renderStyle>\n" + 
                "     <engineStyle>" + this.sessionInfo.engineStyle + "</engineStyle>\n" + 
                "     <user>" + this.sessionInfo.user + "</user>\n" + 
                "     <pass>" + this.sessionInfo.pass + "</pass>\n" + 
                "  </sessionInfo>\n" +
		"  <commandInfo>\n" +
		"    <dest>" + this.commandInfo.destinationId + "</dest>\n" +
		"  </commandInfo>\n" +
                "  <commandArgs>\n";
  for (i in this.commandArguments) {
    q +=        "    <arg><![CDATA[" + this.commandArguments[i] + "]]></arg>\n";
  }
  q +=   	"  </commandArgs>\n" + 
                "</seamarkRequest>\n";  
  return q;
}

/////////////////////////////////////
// SeamarkResponse - Ajax response returned by Seamark Navigator in response to a SeamarkRequest
function SeamarkResponse(responseName, commandInfo, commandResult) {
  var msg = "Creating Seamark Response name = " + responseName + "\n";
  msg += " commandInfo = " + commandInfo + "\n";
  msg += " commandResult = " + commandResult + "\n";
  //alert(msg);
  this.responseName  = responseName;
  this.commandInfo   = commandInfo;
  this.commandResult = commandResult;
}

// Fire off a seamarkRequest - for now we only support stateless request, meaning we create a new session each time
function executeRequest(seamarkRequest) {
  seamarkRequest.sessionId = "newSession";
  var requestXML = seamarkRequest.renderAsXML();
  var callback = {
    success: function(o) {
      var msg = "responseText = " + o.responseText + "\n";
      msg    += "responseHeaders = " + o.getAllResponseHeaders + "\n";
      msg    += "responseXML = " + o.responseXML + "\n";
      msg    += "readyState  = " + o.readyState + "\n";
      msg    += "status      = " + o.status + "\n";
      //alert(msg);
      if (!handleErrors(o.responseXML)) {
	var response = parseResponse(o.responseXML);
	handleSeamarkResponse(response);
      }
    },
    failure: function(o) {
      alert('Failure code ' + o.status + " while accessing " + ajaxURL + " : " + o.statusText);
    }
  }
  try {
    var connectionObject = YAHOO.util.Connect.asyncRequest('POST', ajaxURL, callback, requestXML);
  } catch (e) {
    alert('Error while accessing ' + ajaxURL + ' : ' + e);
  }  
}

function handleErrors(xmlResponse) {
  var root = xmlResponse.getElementsByTagName("seamarkResponse")[0];
  var errorElement = root.getElementsByTagName("error")[0];
  if (errorElement) {
    var messageElement = root.getElementsByTagName("errorMessage")[0];
    var stackTraceElement = root.getElementsByTagName("errorStacktrace")[0];
    var message = messageElement.childNodes[0].nodeValue;
    var stackTrace = stackTraceElement.childNodes[0].nodeValue;
    alert("Error occurred: " + message + "\nServer Stacktrace:\n" + stackTrace + "");
    return true;
  }
  return false;
}


function handleSeamarkResponse(response) {
  // Todo: figure out how to dispatch based on responseName
  //alert('in handleseamrkResponse\nResponse=' + response);
  if (response.responseName == 'CreateSeamarkSession') {
    handleCreateSession(response);
  } else if (response.responseName == 'RenderResult') {
    handleRenderResult(response);
  } else if (response.responseName == 'PivotPopup') {
    handlePivotPopup(response);
  } else {  
    //alert("Error: don't have a handler for response " + responseName);
  }
}

function parseResponse(xmlResponse) {
  var root = xmlResponse.getElementsByTagName("seamarkResponse")[0];
  var name   = getResponseName(xmlResponse);
  var info   = getResponseInfo(xmlResponse);
  var result = getResponseResult(xmlResponse);
  var response = new SeamarkResponse(name, info, result);
  return response;
}

function getResponseName(xmlRoot) {
  var nameElement = xmlRoot.getElementsByTagName("command")[0];
  var textContent = nameElement.firstChild.nodeValue;
  return textContent;
}

function getResponseInfo(xmlRoot) {
  var infoElement = xmlRoot.getElementsByTagName("commandInfo")[0];
  var destElement = infoElement.getElementsByTagName("dest")[0];
  var extraInfoElement = infoElement.getElementsByTagName("extraInfo")[0];
  var dest = destElement.firstChild.nodeValue;
  var extraInfo = extraInfoElement.firstChild.nodeValue;
  var info = new SeamarkCommandInfo(dest, extraInfo);
  return info;
}

function getResponseResult(xmlRoot) {
  var resultElement = xmlRoot.getElementsByTagName("commandResult")[0];
  var content;
  if (/MSIE/.test(navigator.userAgent)) {
    content = resultElement.firstChild.nodeValue;
  } else {
    content = resultElement.textContent;
  }
  content = content.replace(/^\s+/, "");
  content = content.replace(/\s+$/, "");
  return content;
}

/////////////////////////////
// Result handlers
function handlePivotPopup (response) {
  var dest = response.commandInfo.destinationId;
  var html = response.commandResult;  
  //alert("PivotPopup dest=" + destination + "\nhtml=" + html);
  var title = response.commandInfo.extraInfo;
  showPivotPopup(dest, title, html);
}

var maxPopupHeight = 500;   // max height of the pivot popups

function createPivotPopupPart1(id, title) {
  var pivotPopup = "";
  pivotPopup += "<div id='pivotPanel" + id + "'>\n";
  pivotPopup += "  <div class='hd'>\n";
  pivotPopup += "    <div class='tl'></div>\n";
  pivotPopup += "    <span>" + title + "</span>\n";
  pivotPopup += "    <div class='tr'></div>\n";
  pivotPopup += "  </div>\n";
  return pivotPopup;
}

function createPivotPopupPart3(body) {
  var pivotPopup = "";
  pivotPopup += "     <table style=''>\n";
  pivotPopup += "       " + body + "\n";
  pivotPopup += "     </table>\n";
  pivotPopup += "    </div>\n"
  pivotPopup += "  </div>\n";
  pivotPopup += "  <div class='ft'>\n";
  pivotPopup += "    <div class='bl'></div>\n";
  pivotPopup += "    <span>" + "<!--footer text goes here-->"  + "</span>\n";
  pivotPopup += "    <div class='br'></div>\n";
  pivotPopup += "  </div>\n";
  pivotPopup += "</div>\n";
  return pivotPopup;
}

function createStandardPivotPopupHTML(id, title, body) {
  var part2 = "    <div class='scrollpanel' style='background-color:#ebf1ff'>\n";
  return createPivotPopupPart1(id, title) + part2 + createPivotPopupPart3(body);
}

function createShortPivotPopupHTML(id, title, body) {
  //  var part2 = "  <div class='bd' style='height:" + '500 + "'>\n";
  var popupBodyHeight = maxPopupHeight;
  var part2 = "  <div class='bd' style='height:" + popupBodyHeight + "px'>\n";
  part2    += "    <div class='scrollpanel' style='background-color:#ebf1ff'>\n";
  var pivotPopup = createPivotPopupPart1(id, title) + part2 + createPivotPopupPart3(body);
  return pivotPopup;
}

// Useful for testing when the real popups get screwed up
function createTestPivotPopupHTML(id) {
  var p = "";
  p += "<div id='pivotPanel" + id + "' style='visibility:hidden'/>\n";
  p += "  <div class='hd'>Test Panel</div>\n";
  p += "  <div class='bd'>\n";  
  p += "    <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis in risus. Vestibulum a nibh tincidunt elit iaculis laoreet. In pede metus, tristique non, consectetuer a, vestibulum vel, enim. Curabitur neque magna, pulvinar sit amet, lobortis viverra, porta non, dui. Donec tempor, arcu quis interdum pellentesque, dui dolor gravida pede, in iaculis justo tortor venenatis ligula. Cras non pede vel risus egestas faucibus. Nam pulvinar lobortis nisi. In vehicula venenatis sapien.</p>\n";
  p += "    <p style='margin-bottom:0px'>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam et risus ut est adipiscing congue. Praesent ut justo. Proin hendrerit urna eget eros. Curabitur condimentum tempor diam. Pellentesque tortor odio, sollicitudin eget, pellentesque ut, ullamcorper a, justo. Nam tellus pede, fermentum ac, sollicitudin sed, mollis vel, turpis. Fusce pulvinar nibh et erat. Praesent purus nibh, fermentum ac, imperdiet vel, aliquet eu, mi. Praesent non nisi ac mauris tempor ultricies. Nulla mollis tellus porta leo. Nunc accumsan dapibus tellus. Nunc nec nunc.</p>\n";
  p += "  </div>\n";
  p += "</div>\n";
  return p;
}


// Create HTML for a popup, create a div, and stuff the HTML into the div.  Return the id of the popup panel
function createPivotPopup(id, title, body) {
  //  alert("in create pivotpopup testingrendered, id = " + id + ", title = " + title + ", body = " + body);
  var pivotPopup = createStandardPivotPopupHTML(id, title, body);
  //var pivotPopup = createShortPivotPopupHTML(id, title, body);
  //var pivotPopup = createTestPivotPopupHTML(id);
  var pivotPopupDiv = document.createElement("div");
  var pivotPopupDivId = 'pivotPopupDiv' + id;
  pivotPopupDiv.setAttribute("id", pivotPopupDivId);
  document.body.appendChild(pivotPopupDiv);
  var pivotPopupDivEl = document.getElementById(pivotPopupDivId);
  YAHOO.util.Dom.setStyle(pivotPopupDivId, 'width', '40em');

  var msg = 'creating ' + pivotPopupDivId;
  YAHOO.log(msg,'info')
  //alert('stuffing:\n' + pivotPopup);
  pivotPopupDivEl.innerHTML = pivotPopup;
  var pivotPanelId = 'pivotPanel' + id;
  
  var pivotPanelEl = document.getElementById(pivotPanelId);
  var ppHeight = pivotPanelEl.offsetHeight;
  // Here we check to see if the popup is taller than our preferred height, and if so
  //   we regenerate it entirely.  This is really ugly, but IE6 doesn't respect max-height.
  if (ppHeight > maxPopupHeight) {
      pivotPopup = createShortPivotPopupHTML(id, title, body);
      pivotPopupDivEl.innerHTML = pivotPopup;
      var newPPheight = pivotPanelEl.offsetHeight;
  } 
  return pivotPanelId;
}

function showPivotPopup (id, title, body) {
  var pivotAction = document.getElementById("pivotAction" + id);
  var pos = YAHOO.util.Dom.getXY(pivotAction);
  pos[0] -= 100;
  pos[1] -= 0;
  var pivotPanelId =   createPivotPopup(id, title, body);

  YAHOO.siderean.panels.pivotPanel = new YAHOO.widget.Panel(pivotPanelId, { width:"40em", fixedcenter: false, constraintoviewport: true, underlay:"none", close:true, visible:false, draggable:true, modal:false } );
  YAHOO.siderean.panels.pivotPanel.render();
  YAHOO.siderean.panels.pivotPanel.cfg.setProperty("xy", pos);
  YAHOO.siderean.panels.manager.register(YAHOO.siderean.panels.pivotPanel);
  YAHOO.siderean.panels.manager.focus(YAHOO.siderean.panels.pivotPanel);
  YAHOO.siderean.panels.pivotPanel.show();
  
  // START TEST
  /*
  YAHOO.siderean.panels.testPanel = new YAHOO.widget.Panel("testPanel", 
					    { width:"30em",
						visible:true,
						constraintoviewport:true,
						close:true,
						draggable:true,
						xy:[100,100]
						});
  YAHOO.siderean.panels.testPanel.render();  
  YAHOO.siderean.panels.manager.register(YAHOO.siderean.panels.testPanel);
  */
  // END TEST
  YAHOO.util.Dom.setStyle('pivotPanel' + id, 'opacity', 1.0);
}

/////////////////////////////
// API functions
//

// Popup a javascript "window" showing the results for a single item.  
// Assumes scriptName, soapURL, and modelURI are globals defined by the including script
function execSingleItemPivotPopup(queryURI, resourceURI, id) {
  //  alert("scriptName = " + scriptName + ", soapURL = " + soapURL + ", modelURI = " + modelURI);
  //  alert("in execSingleItemPivotPopup, queryURI = " + queryURI + ", resourceURI = " + resourceURI);
  destination=id;
  extraInfo = "";
  var commandInfo = new SeamarkCommandInfo(destination, extraInfo);
  var sessionInfo = new SeamarkSessionInfo(scriptName, soapURL, modelURI, user ? user:"", pass?pass:"");
  var commandName = 'PivotPopup';
  var commandArgs = new Object();
  commandArgs[0] = queryURI; 
  commandArgs[1] = resourceURI;  
  var seamarkRequest = new SeamarkRequest(commandName, sessionInfo, commandInfo, commandArgs);
  executeRequest(seamarkRequest);
}
