//////////////////////////////////////////////////////////////////////////////////
// PageHandler.js v5.0.0                                                        //
// Copyright ADVIZOR Solutions, Inc. 2005-2008                                  //
//                                                                              //
// Copying, modifying or distributing all or part of the contents of this file  //
// without express written permission is strictly prohibited.                   //
//////////////////////////////////////////////////////////////////////////////////

//
// Referenced Global Vars:
//   g_CurrentPerspective (LoadPage, PageHandler_OnWindowResize, PageHandler_LegendChanged,
//                         PageHandler_OnPerspectiveClick, ShowPerspective)
//   g_WhereAmIOn         (HideLegendImages, RefreshLegendImages)
//   g_ColorLegendOn      (HideLegendImages, RefreshLegendImages)
//

//
// Referenced Classes/Rules:
//   Persp_View		(PageHandler_Load, HidePerspectiveImages, RefreshImage)
//   Persp_ViewFrame	(PageHandler_Load, RefreshPerspectiveLayout)
//   Persp_Tab		(ShowPerspective)
//   Persp_ActiveTab	(ShowPerspective)
//   Persp_Link		(ShowPerspective)
//   Persp_ActiveLink	(ShowPerspective)
//

//
// Referenced Element IDs:
//   Page_PaneFrame	(ShowLoadingMessage)
//   LoadingMsg		(ShowLoadingMessage)
//   WhereAmI		(HideLegendImages, RefreshLegendImages)
//   CompositeLegend	(HideLegendImages, RefreshLegendImages)
//

// manifestXML is the id of the xml data island inserted into each page
var m_manifestDocPH = manifestXML;

var m_AppPathPH;         // The ASP.NET application's virtual application root path on the server
var m_defaultPerspectiveKey;
var m_perspectiveKeys;   // Array of perspective keys
var m_Is5xOrGreaterPage;

var m_perspectiveWidth = 0;
var m_perspectiveHeight = 0;

var m_PrevColorLegendOn = false;
var m_PrevWhereAmIOn = false;

var m_borderWidthFrame = 0;
var m_borderWidthView = 0;

var m_progressBar = new ProgressBar();
var	m_checkingProgress = true;

var m_async = true;

function PageHandler_Load(appPath, pageTitle, defaultPerspectiveKey, Is5xOrGreaterPage) {
    // Initialize member vars
    m_AppPathPH = appPath;
    m_defaultPerspectiveKey = defaultPerspectiveKey;
    m_Is5xOrGreaterPage = Is5xOrGreaterPage;

    // Set browser title
    document.title = pageTitle;

    var frameRule = ServerSupport_GetRule(".Persp_ViewFrame");
    var viewRule = ServerSupport_GetRule(".Persp_View");

    if(frameRule) {
        if (frameRule.style.borderWidth) {
            m_borderWidthFrame = frameRule.style.borderWidth;
            m_borderWidthFrame = m_borderWidthFrame.replace("px", "");
        }
    }

    if(viewRule) {
        if (viewRule.style.borderWidth) {
            m_borderWidthView = viewRule.style.borderWidth;
            m_borderWidthView = m_borderWidthView.replace("px", "");
        }
    }

    var i;
    var j;
    var perspKeyAttr;
    var perspectiveKeysInProject;
    var numPerspectiveKeysPublished = 0;
    var xPath = "//Manifest/Perspective";
    var perspNodes = m_manifestDocPH.selectNodes( xPath );

    // Create an array for the perspective keys
    perspectiveKeysInProject = new Array(perspNodes.length);

    // Save perspective keys to array
    for( i = 0; i < perspNodes.length; i++ ) {
        perspKeyAttr = perspNodes[i].attributes.getNamedItem("name");
        perspectiveKeysInProject[i] = perspKeyAttr.value;
    }

    for (i = 0; i < perspectiveKeysInProject.length; i++) {
        if (document.getElementById(perspectiveKeysInProject[i]) != null) {
            numPerspectiveKeysPublished++;
        }
    }

    j = 0;
    m_perspectiveKeys = new Array(numPerspectiveKeysPublished);
    for (i = 0; i < perspectiveKeysInProject.length; i++) {
        if (document.getElementById(perspectiveKeysInProject[i]) != null) {
            m_perspectiveKeys[j] = perspectiveKeysInProject[i];
            j++;
        }
    }

    // Allow page to refresh and display html before executing client-side page load script
    ShowLoadingMessage(true);
    setTimeout("LoadPage()", 1);
}

function LoadPage() {
	if ( m_async ) {
		AsiInitialize(m_manifestDocPH, m_AppPathPH, OnAsiInitialize);

		// Begin checking progress
		CheckProgress(0);
	}
	else {
	    OnAsiInitialize(AsiInitialize(m_manifestDocPH, m_AppPathPH), true);
	}
}

// Handle callback from AsiInitialize()
function OnAsiInitialize(success, processCmd) {
	if (processCmd) {
	
		if (success) {
		    ShowLoadingMessage(false);

		    TabSupport_Init();
		    TabSupport_ResizeTabFrame();

		    if ( !m_Is5xOrGreaterPage ) {
				// Insert footer text before the end of the AsiFooter element
		        InsertFooter();
		    }

		    g_CurrentPerspective = m_defaultPerspectiveKey;
		    m_perspectiveWidth = CurrentPerspectiveWidth(g_CurrentPerspective);
		    m_perspectiveHeight = CurrentPerspectiveHeight(g_CurrentPerspective);

		    // Show initial perspective
		    ShowPerspective(m_defaultPerspectiveKey);
		}
		else {
			var loadingImage = document.getElementById('loadingImage')
			var pathParts = loadingImage.src.split('/');
			
			// Hide the progress bar
			m_progressBar.setVisible(false);
			
			// Change the "loading..." image to the "failed" image
			pathParts[pathParts.length - 1] = "LoadingProjectFailed.gif";
			loadingImage.src = pathParts.join('/');
		}
	}
	else {
		// Stop checking progress now
		m_checkingProgress = false;
		
		// Set the progress bar to 100%, in case it is not quite there yet
		m_progressBar.update(100);

		setTimeout("OnAsiInitialize(" + success + ", true)", 0);
	}
}

function CheckProgress(delayms) {
	setTimeout("AsiSessionCreationStatus( OnCheckProgress )", delayms);
}

// Handle callback from AsiSessionCreationStatus()
function OnCheckProgress( eventResult ) {
	// Show the progress bar if it isn't visible yet
	if (!m_progressBar.getVisible()) {
		m_progressBar.setVisible(true);
	}

	var polldelay = 30;	// smooth update rate
	if( eventResult.success == true ) {
		// Update the progress bar
		if (eventResult.percentLoaded > 0) {
			m_progressBar.update(eventResult.percentLoaded);
			polldelay = 500;	// slow down polling
		}
		else {
			m_progressBar.update();
		}
	}
	else {
		// It is normal to get an error when the project
		// starts to load, so just update the progress bar
		m_progressBar.update();		
	}

	// Continue checking progress if applicable
	if (m_checkingProgress) {
		CheckProgress(polldelay);
	}
}

function ShowLoadingMessage(turnOn) {
    var pageFrame = document.getElementById('Page_PaneFrame');
    var loadingMsg = document.getElementById('LoadingMsg');
    if (turnOn) {
        var left = ServerSupport_AbsoluteLeftNode(pageFrame);
        var top = ServerSupport_AbsoluteTopNode(pageFrame);
        var width = pageFrame.parentElement.clientWidth;
        var height = pageFrame.parentElement.clientHeight;
		
        pageFrame.style.display = "none";
        loadingMsg.style.display = "block";
        loadingMsg.style.pixelLeft = left + (width / 2) - (loadingMsg.clientWidth / 2);
        loadingMsg.style.pixelTop = top + (height / 2) - (loadingMsg.clientHeight / 2);
    }
    else {
        loadingMsg.style.display = "none";
        pageFrame.style.display = "block";
    }
}

function PageHandler_OnWindowResize(doEvents) {
	if ( g_CurrentPerspective !== undefined ) {
	    if ( !doEvents ) {
	        HidePerspectiveImages(g_CurrentPerspective);
	        HideLegendImages();

	        // This is necessary here so that perspective list shrinks to fit new window size.
	        // Otherwise, we may end up with a perspective that is larger than the browser window
	        // and we'll see scroll bars.
	        TabSupport_ResizeTabFrame();

	        m_perspectiveWidth = CurrentPerspectiveWidth(g_CurrentPerspective);
	        m_perspectiveHeight = CurrentPerspectiveHeight(g_CurrentPerspective);
	        RefreshPerspectiveLayout(g_CurrentPerspective, m_perspectiveWidth, m_perspectiveHeight);

	        setTimeout("PageHandler_OnWindowResize(true)", 1);
	        return;
	    }

	    // Fix for MR8721 - This is necessary here so arrows are repositioned correctly
	    // for cases where page is inside of IFrame (or other elements like a table).
	    TabSupport_ResizeTabFrame();

	    RefreshPerspectiveImages(g_CurrentPerspective);
	    RefreshLegendImages();
	}
}

function PageHandler_LegendChanged(doEvents) {
    if ( !doEvents ) {
        HidePerspectiveImages(g_CurrentPerspective);
        HideLegendImages();

        m_perspectiveWidth = CurrentPerspectiveWidth(g_CurrentPerspective);
        m_perspectiveHeight = CurrentPerspectiveHeight(g_CurrentPerspective);
        RefreshPerspectiveLayout(g_CurrentPerspective, m_perspectiveWidth, m_perspectiveHeight);

        setTimeout("PageHandler_LegendChanged(true)", 1);
        return;
    }

    RefreshPerspectiveImages(g_CurrentPerspective);
    RefreshLegendImages();
}

function PageHandler_OnPerspectiveClick(perspKey) {
    if (g_CurrentPerspective != perspKey) {
        ShowPerspective(perspKey);
    }
    // Move focus off of selected item.
    window.focus();
}

function ShowPerspective(perspKey) {
    var curPersp;
    var i;

    g_CurrentPerspective = perspKey;
    curPersp = document.getElementById(g_CurrentPerspective);

    for (i = 0; i < m_perspectiveKeys.length; i++) {
        if ( m_perspectiveKeys[i] != perspKey ) {
			if( document.getElementById("tab" + m_perspectiveKeys[i]).className != "Separator_Tab" ) {
				document.getElementById(m_perspectiveKeys[i]).style.display = "none";
				document.getElementById("tab" + m_perspectiveKeys[i]).className = "Persp_Tab";
				document.getElementById("link" + m_perspectiveKeys[i]).className = "Persp_Link";
			}
		}
    }

    curPersp.style.display = "block";
    document.getElementById("tab" + perspKey).className = "Persp_ActiveTab";
    document.getElementById("link" + perspKey).className = "Persp_ActiveLink";

    var perspNode = m_manifestDocPH.selectSingleNode( "//Manifest/Perspective[@name='" + perspKey + "']" );
    var perspTableDisplayName = perspNode.attributes.getNamedItem( "defaultTableDisplayName" ).value;
	var perspColorDisplayNode = perspNode.attributes.getNamedItem( "defaultColorDisplayName" );

	if( perspColorDisplayNode != null ) {
		ToolbarSupport_SetCurrentTableColor( perspTableDisplayName, perspColorDisplayNode.value );
	}
	else {
		ToolbarSupport_SetCurrentTable(perspTableDisplayName);
	}

    // Set WeightBy dropdown value
    WeightByDropDown.value = curPersp.weightBy;

    if (curPersp.lastWidth != m_perspectiveWidth || curPersp.lastHeight != m_perspectiveHeight) {
        HidePerspectiveImages(g_CurrentPerspective);
        RefreshPerspectiveLayout(g_CurrentPerspective, m_perspectiveWidth, m_perspectiveHeight);
        setTimeout("RefreshPerspectiveImages('" + g_CurrentPerspective + "')", 1);
    }
    else {
        // Pick up any changes for the current perspective from changes to
        // selection state or newly included/excluded data in previous perspective.
        AsiRefreshImages();
    }
}

function HidePerspectiveImages(perspID) {
    var divPerspective;
    var imgNode;
    var i;

    i = 0;
    divPerspective = document.getElementById(perspID);
	if (divPerspective) {
	    imgNodes = divPerspective.getElementsByTagName("img");
	    for (i = 0; i < imgNodes.length; i++) {
	        imgNode = imgNodes[i];
	        if (imgNode.className == "Persp_View") {
	            imgNode.style.visibility = "hidden";
	            imgNode.height = 0;
	            imgNode.width = 0;
	        }
	    }
	}
}

function HideLegendImages() {
    var imgNode;

    if ( g_WhereAmIOn ) {
        imgNode = document.getElementById('WhereAmI');
        imgNode.style.visibility = "hidden";
        imgNode.height = 0;
        imgNode.width = 0;
    }
    if ( g_ColorLegendOn ) {
        imgNode = document.getElementById('CompositeLegend');
        imgNode.style.visibility = "hidden";
        imgNode.height = 0;
        imgNode.width = 0;
    }
}

function RefreshPerspectiveImages(perspID) {
    var divPerspective;
    var imgNodes;
    var i;

    divPerspective = document.getElementById(perspID);
    imgNodes = divPerspective.getElementsByTagName("img");

    AsiSuspendImages();
	
	// Create an object to track the image refresh status
	var refreshStatus = new Object;
	refreshStatus.refreshedImages = 0;
	refreshStatus.totalImages = imgNodes.length;	
	
    for (i = 0; i < imgNodes.length; i++) {
		if ( m_async ) {
			// Asynchronous
			RefreshImage(imgNodes[i], function() {OnRefreshPerspectiveImages(refreshStatus);});
		}
		else {
			// Synchronous
	        RefreshImage(imgNodes[i]);
			OnRefreshPerspectiveImages(refreshStatus);
		}
    }
}

// Handle callback from RefreshPerspectiveImages()
function OnRefreshPerspectiveImages(refreshStatus) {
	// Another image has been refreshed, so increment the counter
	refreshStatus.refreshedImages++;
	
	if ( refreshStatus.refreshedImages == refreshStatus.totalImages ) {
		// All the images have been refreshed now
		AsiRefreshImages();
	}
}

function RefreshLegendImages() {
    var imgNode;

    if ( g_WhereAmIOn ) {
        imgNode = document.getElementById('WhereAmI');
		// If async, pass an empty handler to make the call asynchronously
		RefreshImage(imgNode, (m_async ? function() {} : undefined));
    }
    if ( g_ColorLegendOn ) {
        imgNode = document.getElementById('CompositeLegend');
		// If async, pass an empty handler to make the call asynchronously
		RefreshImage(imgNode, (m_async ? function() {} : undefined));
    }
}

function RefreshImage(imageNode, handlerMethod) {
    var newHeight;
    var newWidth;

    if (imageNode.className == "Persp_View") {
        newHeight = imageNode.parentElement.offsetHeight - (m_borderWidthFrame * 2) - (m_borderWidthView * 2);
        newWidth = imageNode.parentElement.offsetWidth - (m_borderWidthFrame * 2) - (m_borderWidthView * 2);

        if (imageNode.lastHeight != newHeight || imageNode.lastWidth != newWidth) {
            if (newHeight > 0 && newWidth > 0) {
                imageNode.lastHeight = newHeight;
                imageNode.lastWidth = newWidth;
                imageNode.height = newHeight;
                imageNode.width = newWidth;

				if ( handlerMethod ) {
					// Create a meta handler
					var metaHandler = function() {
						OnRefreshImage(imageNode);
						handlerMethod();
					};
					
					// Asynchronous
					AsiResizeView(imageNode.id, imageNode.height, imageNode.width, metaHandler);
				}
				else {
					// Synchronous
				    AsiResizeView(imageNode.id, imageNode.height, imageNode.width);
					OnRefreshImage(imageNode);
				}
            }
            else {
                imageNode.height = imageNode.lastHeight;
                imageNode.width = imageNode.lastWidth;
				imageNode.style.visibility = "visible";
            }
        }
        else {
            imageNode.height = imageNode.lastHeight;
            imageNode.width = imageNode.lastWidth;
			imageNode.style.visibility = "visible";
        }
    }
}

// Handle callback from RefreshImage()
function OnRefreshImage(imageNode) {
	if ( imageNode.src.length > 0 ) {
		imageNode.style.visibility = "visible";
	}	
	else {
		// The first time through, the image will not have a source,
		// and if we set it to be visible, an unsightly empty image
		// will be shown for a few seconds.  To avoid that, create an
		// ad hoc onload handler that will set the image to be visible
		// and then jettison itself.
		var onloadHandler = function() {
			this.style.visibility = "visible"
			this.onload = null;
		};
	
		imageNode.onload = onloadHandler;
	}
}

function CurrentPerspectiveWidth(perspID) {
	return document.getElementById(perspID).clientWidth;
}

function CurrentPerspectiveHeight(perspID) {
	return document.getElementById(perspID).clientHeight;
}

function RefreshPerspectiveLayout(perspID, perspWidth, perspHeight) {
    var divPerspective;
    var divNodes;
    var viewFrame;
    var i;

    var perspTop = 0;
    var perspLeft = 0;

	divPerspective = document.getElementById(perspID);
	perspTop = ServerSupport_AbsoluteTopNode(divPerspective);
	perspLeft = ServerSupport_AbsoluteLeftNode(divPerspective);

	i = 0;
	divNodes = divPerspective.getElementsByTagName("div");
	for (i = 0; i < divNodes.length; i++) {
		viewFrame = divNodes[i];
		if (viewFrame.className == "Persp_ViewFrame") {
			viewFrame.style.left = Math.round(((parseInt(viewFrame.origLeft) / 100) * perspWidth)) + perspLeft;
			viewFrame.style.top = Math.round(((parseInt(viewFrame.origTop) / 100) * perspHeight)) + perspTop;
			viewFrame.style.width = Math.round((parseInt(viewFrame.origWidth) / 100) * perspWidth);
			viewFrame.style.height = Math.round((parseInt(viewFrame.origHeight) / 100) * perspHeight);
		}
	}

	divPerspective.lastWidth = perspWidth;
	divPerspective.lastHeight = perspHeight;
}

// ProgressBar class encapsulates progress bar functionality
function ProgressBar(barWidth, barIncrement) {
	var m_bar = document.getElementById("progressBar");
	var m_leftSegment = document.getElementById("progressBarLeft");
	var m_middleSegment = document.getElementById("progressBarMiddle");
	var m_rightSegment = document.getElementById("progressBarRight");
	var m_label = document.getElementById("progressBarLabel");
	var m_barWidth = 20;
	var m_barIncrement = 1;
	var m_indeterminateMode = false;

	if (barWidth) {
		m_barWidth = barWidth;
	}
	if (barIncrement) {
		m_barIncrement = barIncrement;
	}

	//
	//	Public methods
	//
	
	this.getVisible = function() {
		var visibility = false;
		
		if (m_bar.style.visibility == "visible") {
			visibility = true;
		}
		
		return visibility;
	};
	
	this.setVisible = function(visible) {
		var visibility = "hidden";
		
		if (visible) {
			visibility = "visible";
		}
		
		m_bar.style.visibility = visibility;
	};
	
	// Update the progress bar
	this.update = function(percent) {

		if (percent) {
			// A percentage has been provided, so we are in 
			// determinate mode
			if (m_indeterminateMode) {
				m_indeterminateMode = false;
			}

			setBar(percent);
		}
		else {
			// A percentage has not been provided, so we are in 
			// indeterminate mode
			if (!m_indeterminateMode) {
				reset();
				m_indeterminateMode = true;
			}
			
			incrementBar();
		}
	};

	//
	//	Private methods
	//
	
	var reset = function() {
		m_leftSegment.width = "";
		m_middleSegment.width = "";
		m_rightSegment.width = "100%";
		m_label.innerText = "";
	};

	// Set the determinate bar to the specified percentage
	var setBar = function(percent) {
		var done = Math.min(percent,100);
		var remain = 100 - done;
		
		m_leftSegment.width = "";
		m_middleSegment.width = ( done <= 0 ? "" : done + "%" );
		m_rightSegment.width = ( remain <= 0 ? "" : remain + "%" );
		
		m_label.innerText = done + "%";
	};
	
	// Move the indeterminate bar by 1 increment unit from its current
	// position, wrapping if necessary
	var incrementBar = function() {
		var left = m_leftSegment.width === "" ? 0 : parseInt( m_leftSegment.width, 10 );
		var middle = m_middleSegment.width === "" ? 0 : parseInt( m_middleSegment.width, 10 );
		var right = m_rightSegment.width === "" ? 0 : parseInt( m_rightSegment.width, 10 );
		
		if ( right > 0 ) {
			// The bar is moving right but has not touched the
			// right border yet
			right -= m_barIncrement;

			if ( m_barWidth + right <= 100 ) {
				// The bar is in the middle somewhere
				middle = m_barWidth;
			}
			else {
				// The bar is emerging from the left border
				middle = 100 - right;
			}
			
			left = 100 - ( middle + right );
		}
		else {
			if ( left < 100 ) {
				// The bar is moving into the right border
				left += m_barIncrement;
				
				middle = 100 - left;
			}
			else {
				// The bar has disappeared into the right border,
				// so start over (reemerge from left border).
				left = 0;
				right = 100;
			}
		}
		
		m_leftSegment.width = ( left <= 0 ? "" : left + "%" );
		m_middleSegment.width = ( middle <= 0 ? "" : middle + "%" );
		m_rightSegment.width = ( right <= 0 ? "" : right + "%" );
	};
}

