/********************************************************************************
  Copyright, 2004, Intergraph Corporation. All Rights Reserved.
  The product licensee is granted permission to copy and distribute 
  this script only to support the product SVG output and licensee's 
  associated web sites, and to prepare derivative works solely for 
  internal use. All other rights reserved.
**********************************************************************************/


/*********************************************************/
//---   CORE FUNCTIONS  --- 
// Requires:
//   -n/a
//
/*********************************************************/


//--GLOBAL VARIABLES/CONSTANTS-----

// Error codes - Used in ALL JS files that depend on the CoreFunctions
var _gwm_E_SUCCESS            = 0;      // Success
var _gwm_E_UNSPECIFIED        = -1;     // Unspecified err; internal flag for not-success.
var _gwm_E_VIEWERMENU         = -51;    // viewer menu processing error
var _gwm_E_VIEWERMENUITEM     = -52;    // viewer menu item processing error
var _gwm_E_GETELEMENT         = -100;   // err processing an SVG element
var _gwm_E_UNKNOWN            = -101;   // unknown or unexpected error
var _gwm_E_GETLAYER           = -102;   // err processing a layer
var _gwm_E_PARAMNULL          = -103;   // a required parameter is null or empty string ("")
var _gwm_E_HANDLERNOTFUNCTION = -104;   // an event handler parameter is not a function reference
var _gwm_E_ELEATTR            = -105;   // error processing an element attribute
var _gwm_E_PARAMINVALID       = -110;   // invalid parameter
var _gwm_E_ELEIDINVALID       = -111;   // invalid (SVG) Element ID
var _gwm_E_NOREDLINES         = -150;   // there are no redlines to process
var _gwm_E_INTERNAL           = -200;   // internal logic or variable fault


//---CORE OBJECT/INTERFACE---------------------------------
//---------------------------------------------------------
function _gwmCoreObject()
{
  //--PROPERTIES-----
  this.svgDoc=null;
  this.svgRoot=null;
  this.tooltipText=null;
  this.tooltipRect=null;
  this.tooltipGroup=null;
  this.tooltipFontSize=12;
  this.iViewH=0;
  this.iViewW=0;
  this.iViewCtrlWidth=0;
  this.iViewCtrlHeight=0;
  this.ns = "gmwmsvg";
  this.xmlns = 'xmlns:gmwmsvg="http://www.intergraph.com/GeoMedia/wmsvg"';  

  //--METHODS-----
  this.init                   = _gwmCoreInit;
  this.actionHandler          = _gwmActionHandler;
  this.launchAction           = _gwmLaunchAction;
  this.getAction              = _gwmGetEleAction;
  this.setAction              = _gwmSetEleAction;

  this.getSVGTransMatrix      = _gwmGetSVGTransMatrix;
  this.getTransSVGPoint       = _gwmGetTransSVGPoint;
  this.getTransSVGPointMtx    = _gwmGetTransSVGPointMtx;
  
  this.getTooltip             = _gwmGetEleTooltip;
  this.setTooltip             = _gwmSetEleTooltip;
  this.showTooltip            = _gwmShowTooltip;
  this.clearTooltip           = _gwmClearTooltip;
  this.getTooltipRectStyle    = _gwmGetTtipRectStyle;
  this.getTooltipTextStyle    = _gwmGetTtipTextStyle;
  this.setTooltipRectStyle    = _gwmSetTtipRectStyle;
  this.setTooltipFontSize     = _gwmSetTooltipFontSize;
  this.setTooltipTextStyle    = _gwmSetTtipTextStyle;

  this.highlightHandler       = _gwmHighlight;
  this.tooltipHandler         = _gwmTooltipHandler;
  this.updateLogo             = _gwmUpdateLogo;
  this.updateView             = _gwmUpdateView;
}

// Globals 
var _gwmCore = new _gwmCoreObject();


//=========================================================
function _gwmOnSVGLoadEx(evt)
{
  _gwmCore.svgDoc = evt.getTarget().getOwnerDocument();
  var iRet = _gwmCoreInit(null);
  //TO DO: process any err condition
}

//=========================================================
function _gwmOnSVGLoad()
{
  _gwmCore.svgDoc = document;
  var iRet = _gwmCoreInit(null);
  //TO DO: process any err condition
}

//=========================================================
function _gwmCoreInit(svgDoc)
{
var doc = null;

  if( !_gwmCore.svgDoc && null != svgDoc) 
    _gwmCore.svgDoc = svgDoc;

  doc = _gwmCore.svgDoc;
  if( !doc ) return _gwm_E_UNKNOWN;
  
  _gwmCore.svgRoot      = doc.getElementById('gwmroot');
  _gwmCore.tooltipText  = doc.getElementById('gwmtooltiptext');
  _gwmCore.tooltipRect  = doc.getElementById('gwmtooltiprect');
  _gwmCore.tooltipGroup = doc.getElementById('gwmtooltip');
  
  _gwmCore.setTooltipFontSize();

  var maskRect = doc.getElementById('gwmmaskrect');
  _gwmCore.iViewH = maskRect.getAttribute('height');
  _gwmCore.iViewW = maskRect.getAttribute('width');

  _gwmCore.updateLogo();
  
  return _gwm_E_SUCCESS;
}

//=========================================================
function _gwmUpdateLogo()
{
  var Logo = _gwmCore.svgDoc.getElementById('gwmlogo'); 
  if( Logo )
  {
    var LogoBox=Logo.getBBox();
    var LogoRect=_gwmCore.svgDoc.getElementById("gwmlogorect");  
    LogoRect.setAttribute ("x",50);
    LogoRect.setAttribute ("y", _gwmCore.iViewH-300-LogoBox.height);
    LogoRect.setAttribute ("width",LogoBox.width+200);
    LogoRect.setAttribute ("height",LogoBox.height+200);
    Logo.setAttribute ("x",150);
    Logo.setAttribute ("y", _gwmCore.iViewH-200-LogoBox.height - LogoBox.y);
  }
}

//=========================================================
function _gwmActionHandler(evt)
{
var ele = evt.target;
  if (null != ele.correspondingUseElement)
    ele = ele.correspondingUseElement;

  // ignore background clicks
  if( ele.getAttribute('id') == "gwmbg" ) return;
  var a = _gwmCore.getAction( ele );
  if( a != "" ) _gwmCore.launchAction( a );
}

//=========================================================
function _gwmGetEleAction( ele )
{
  if( !ele ) return "";
  if (null != ele.correspondingUseElement)
    ele = ele.correspondingUseElement;
  var a=ele.getAttribute(_gwmCore.ns + ":act");
  if(a == "")
  {
    ele = ele.parentNode;
    a=ele.getAttribute(_gwmCore.ns + ":act");
  }
  return a;
}

//=========================================================
function _gwmLaunchAction( a )
{
  if( null == a || a == "" ) return;
  var sBuf = a.toLowerCase();
  if( sBuf.indexOf("javascript") !=-1 ) window.eval( a );
  else window.location = a;
  return;
}

//=========================================================
function _gwmSetEleAction( ele, a )
{
  //allow empty actions in order to reset them.
  if( !ele ) return "";
  if (null != ele.correspondingUseElement)
    ele = ele.correspondingUseElement;
  ele.setAttribute(_gwmCore.ns + ":act", a);
}

//=========================================================
function _gwmTooltipHandler(evt, tt, bOn)
{
var t = "";
var ele = evt.getTarget();

  if( !ele ) return;
  if (null != ele.correspondingUseElement)
    ele = ele.correspondingUseElement;
  if( null == tt || tt == "" )
    t = _gwmCore.getTooltip( ele );
  else
    t = tt;

  if( bOn && t != "" )
  {
    _gwmCore.showTooltip(evt,null,t);
  }
  else if( !bOn && t != "" )
  {
    _gwmCore.clearTooltip();
  }
  return;
}

//=========================================================
function _gwmGetEleTooltip( ele )
{
  if (null != ele.correspondingUseElement)
    ele = ele.correspondingUseElement;
  var t=ele.getAttribute(_gwmCore.ns + ":tt");
  if(t == "")
  {
    ele = ele.parentNode;
    t=ele.getAttribute(_gwmCore.ns + ":tt");
  }
  return t;
}

//=========================================================
function _gwmClearTooltip()
{
  _gwmCore.tooltipRect.style.setProperty('display', 'none');
  /***
  _gwmCore.tooltipRect.setAttribute('x', '0');
  _gwmCore.tooltipRect.setAttribute('y', '0');
  _gwmCore.tooltipRect.setAttribute('width', '0');
  _gwmCore.tooltipRect.setAttribute('height', '0');
  ***/
  
  _gwmCore.tooltipText.style.setProperty('display', 'none');
  /***
  _gwmCore.tooltipText.setAttribute('x', '0');
  _gwmCore.tooltipText.setAttribute('y', '0');
  ***/
}

//=========================================================
function _gwmShowTooltip(evt, pt, tt)
{
var locX, locY; //xy location of tooltip group

  if( tt == "" || (!evt && !pt) ) return;
  locX = locY = 0;
  var shift = 8; //fudge factor to get things "right"
  
  if( null != evt ) 
  {
    var ele  = evt.getTarget();
    if (null != ele.correspondingUseElement)
      ele = ele.correspondingUseElement;
    if( ele.getAttribute('id') == "gwmbg" ) return;
    locX = evt.getClientX();
    locY = evt.getClientY();
  }
  else 
  {
    locX = pt.x;
    locY = pt.y;
  }
  
	var mtx = _gwmCore.getSVGTransMatrix();
	var pxToCoord = mtx.a; //pixels per user unit
	var OutP = _gwmCore.svgRoot.createSVGPoint();
	var InP  = _gwmCore.svgRoot.createSVGPoint();
  
	InP.x = locX;
	InP.y = locY;
	OutP = InP.matrixTransform(mtx);

  var ttTxt  = _gwmCore.tooltipText;
  var ttRect = _gwmCore.tooltipRect;
	
	while( ttTxt.hasChildNodes() )
	{
		ttTxt.removeChild(ttTxt.firstChild);
	}
  
  //--Update Txt Ele with actual Tooltip. 
  //  Check for multi-line tooltips (containing newlines (GWMNL)).  
	var ttArray = tt.split("GWMNL");
  var lineCnt = ttArray.length;

  var doc = _gwmCore.svgDoc;
	var data = doc.createTextNode(ttArray[0]);
	ttTxt.appendChild(data);
	for( var i = 1; i < lineCnt; i++ )
	{
    //--Handle problem when data not present for multi-line tooltip. 
    //  Without inserting a space, the later calcs are off and text
    //  gets scrunched onto ttip box outline.
    if( ttArray[i] == "" ) ttArray[i] = " ";
    
		var data  = doc.createTextNode(ttArray[i]);
		var tspan = doc.createElement("tspan");
		tspan.setAttribute("x", ttTxt.getAttribute('x'));
		tspan.setAttribute("dy", "1em");
		tspan.appendChild(data);
		ttTxt.appendChild(tspan);
	}

  //--Set Fontsize to insure consistent size, independent of zoom level.
  ttTxt.style.setProperty('font-size', _gwmCore.tooltipFontSize * pxToCoord);
  ttTxt.style.setProperty('display', 'inline');
  
  //--Update TTip Rectangle based on Txt size
	var ttBox = ttTxt.getBBox();
	var hInPx = parseInt(ttBox.height/pxToCoord);
	var wInPx = parseInt(ttBox.width/pxToCoord);
  
  //--Determine location within current view.
	InP.x = locX + shift;
	if (InP.x + wInPx + shift > _gwmCore.iViewCtrlWidth) 
    InP.x = _gwmCore.iViewCtrlWidth - shift - wInPx;
	InP.y = locY - hInPx - (shift*2);
	if (InP.y < 0) InP.y = 0;
	OutP = InP.matrixTransform(mtx);
  
  //--Place entire Group: Rect and Text.
	_gwmCore.tooltipGroup.setAttribute('transform', 
        "translate(" + OutP.x + "," + OutP.y + ")");
  
  //--Refine TTip rect settings and display.
  var rW=parseInt((wInPx + shift) * pxToCoord);
  var rH=parseInt((hInPx + shift) * pxToCoord);
	ttRect.setAttribute('width', rW);
	ttRect.setAttribute('height', rH);
  ttRect.style.setProperty('display', 'inline');
	ttRect.style.setProperty('stroke-width', pxToCoord);

  //--Create offset of Text within Rect
  var tY = ((rH/2)/lineCnt) + ((ttBox.height/2)/lineCnt);
  ttTxt.setAttribute ('y',tY);
  ttTxt.setAttribute ('x',pxToCoord*3);

}

//=========================================================
function _gwmSetEleTooltip( ele, tt )
{
  if( !ele || null == tt || tt == "" ) return;
  ele.setAttribute(_gwmCore.ns + ":tt", tt);
}
  

//==========================================================
function _gwmGetTtipTextStyle()
{
  if( _gwmCore.tooltipText )
    return( _gwmCore.tooltipText.getAttribute('style') );
  return "";
}

//==========================================================
function _gwmGetTtipRectStyle()
{
  if( _gwmCore.tooltipRect )
    return( _gwmCore.tooltipRect.getAttribute('style') );
  return "";
}

//=========================================================
function _gwmSetTtipTextStyle( sStyle )
{
  if( null == sStyle || sStyle == "" ) return _gwm_E_PARAMNULL;
  if( _gwmCore.tooltipText )
  {
    _gwmCore.tooltipText.setAttribute('style', sStyle);
    _gwmCore.setTooltipFontSize();
  }
  return _gwm_E_SUCCESS;
}

//=========================================================
function _gwmSetTooltipFontSize()
{
  if( !_gwmCore.tooltipText ) return;
  var fs = _gwmCore.tooltipText.style.getPropertyCSSValue('font-size').cssText; 
  if( null != fs && "" != fs && 'undefined' != fs ) 
  {
    var iFs = parseInt(fs);
    if( !(isNaN(iFs)) ) _gwmCore.tooltipFontSize = iFs;
  }
}

//=========================================================
function _gwmSetTtipRectStyle( sStyle )
{
  if( null == sStyle || sStyle == "" ) return _gwm_E_PARAMNULL;
  if( _gwmCore.tooltipRect )
    _gwmCore.tooltipRect.setAttribute('style', sStyle);
  return _gwm_E_SUCCESS;
}

//=========================================================
function _gwmHighlight(evt, classIndex)
{
var ele=evt.getTarget();
if (null != ele.correspondingUseElement)
  ele = ele.correspondingUseElement;

   //return on background mouse events
   if( ele.getAttribute('id') == 'gwmbg' ) return;
    
var par=ele.parentNode;
var component = false;
var parentID;
var collectionEle;
var hClass = ele.getAttribute(_gwmCore.ns + ":hi");
var rClass = null;


  parentID = par.getAttribute('id');
  if( parentID == '' )
  {
    component=true;
    collectionEle=par;
  }
  else if( hClass == '' && 
           (par.getAttribute(_gwmCore.ns + ":hi") == '' ||
            par.getAttribute('class')  == '') ) return;

  if( hClass=='' || component )
  {
    hClass=par.getAttribute(_gwmCore.ns + ":hi");
    rClass = par.getAttribute('class');
    if( rClass != '' && hClass == '' ) return;

    while(parentID!='gwmroot' && hClass=='')
    {
      par = par.parentNode;
      hClass = par.getAttribute(_gwmCore.ns + ":hi"); 
      rClass = par.getAttribute('class');
      if( rClass != '' && hClass == '' ) return;
      parentID = par.getAttribute('id');
    }
  }

  if (hClass=='') return;

  var classes=hClass.split(" ");
  if (component)
  {
	  ele = collectionEle.firstChild;
	  while (ele.nextSibling())
	  {
      ele = ele.nextSibling();
      if (ele.attributes)
      {
        var eleName = ele.nodeName();
        var eleClasses=ele.getAttribute(_gwmCore.ns + ":hi");
        var theClass;
        if (eleClasses=='')
	        theClass = classes[classIndex];
        else
	        theClass =  eleClasses.split(" ")[classIndex];

        if (eleName == "use")
	        ele.setAttribute('xlink:href', "#" + theClass);
        else
	        ele.setAttribute('class', theClass);
		  }
	  }
  }
	else
	{
		var eleName = ele.nodeName();
		if (eleName == "use")
			ele.setAttribute('xlink:href', "#" + classes[classIndex]);
		else
			ele.setAttribute('class', classes[classIndex]);
	}
}

//=========================================================
function _gwmGetSVGTransMatrix()
{

var root = _gwmCore.svgRoot;

  if( !root ) return;

  var mtx  = root.createSVGMatrix();
  
  // root width/height never set. Use global viewCtrl
  var winW = _gwmCore.iViewCtrlWidth;
  if( winW <= 0 ) winW = 1; //to do: what to do about this err condition?
  var winH = _gwmCore.iViewCtrlHeight;
  if( winH <= 0 ) winH = 1; //to do: what to do about this err condition?
  
  var x_ratio = _gwmCore.iViewW/winW;
  var y_ratio = _gwmCore.iViewH/winH;
  
  if (x_ratio<y_ratio)
  {
    var x_diff = winW * y_ratio - _gwmCore.iViewW;
    mtx = mtx.translate(-x_diff/2, 0);
    mtx = mtx.scale( y_ratio );
  }
  else if(x_ratio>y_ratio)
  {
    var y_trans=0;
    var y_diff = winH * x_ratio - _gwmCore.iViewH;
    mtx = mtx.translate(0,-y_diff/2);
    mtx = mtx.scale(x_ratio);
  }
  else
  {
    mtx = mtx.scale(x_ratio);
  }
  var trans=root.getCurrentTranslate();
  var scale=root.getCurrentScale();
  mtx = mtx.scale( 1/scale );
  mtx = mtx.translate(-trans.x, -trans.y);

return mtx;
}

//=========================================================
function _gwmGetTransSVGPoint( evt )
{
var root = _gwmCore.svgRoot;

  var mtx  = _gwmCore.getSVGTransMatrix();
  var OutP = root.createSVGPoint();
  var InP  = root.createSVGPoint();
  InP.x = evt.getClientX();
  InP.y = evt.getClientY();
  OutP  = InP.matrixTransform(mtx);
  return OutP;
}

//=========================================================
function _gwmGetTransSVGPointMtx( evt, mtx )
{
  var root = _gwmCore.svgRoot;
  var OutP = root.createSVGPoint();
  var InP  = root.createSVGPoint();
  InP.x = evt.getClientX();
  InP.y = evt.getClientY();
  OutP  = InP.matrixTransform(mtx);
  return OutP;
}

//=========================================================
function _gwmUpdateView()
{
  var maskRect = _gwmCore.svgDoc.getElementById('gwmmaskrect'); 
  _gwmCore.iViewH = maskRect.getAttribute('height');
  _gwmCore.iViewW = maskRect.getAttribute('width');
}

