/**
 * Super class for all JitkWindows
 */
function JitkWindows() {
	this.animationSpeed = "fast";		// "slow", "normal", "fast" or the number of milliseconds to run the animation (e.g. 1000)
	
	this.collapsable = true;			// show/hide toggle button for expand/collapse
	this.closable = true;				// show/hide close button
	this.movable = true;				// can drag the floating panel?
	this.resizable = false;				// can resize the window?
	this.fittable = true;				// whether to allow fitting of content within window
	this.isFloatingWindow = true;		// whether or not it is a floating window (vs. fixed without titlebar, e.g. accordion)
	this.zIndex = 100;					// stacking order of the panel
	
	this.lastPosX = -1;
	this.lastPosY = -1;
	
	zIndexAll = 500;					// top-most stacking order of all panels
	lastPosXAll = 300;
	lastPosYAll = 100;
}

// attach the superclass to the individual window 
JitkWindow.prototype = new JitkWindows;
JitkWindow.prototype.constructor = JitkWindow;

// event args (that can be exposed) 
function JitkWindowEventArgs(id) {
	this.id = id;
}

/**
 * jitk window class (inherits from JitkWindows)
 */
function JitkWindow(id, title, pageElement) {
	this.inheritsFrom(new EsriPageElement(id));
	this.pageElement = pageElement;
	//this.id = id;
	this.divId = "WindowDiv_" + id;
	//this.windowMgr = null;
	
	// PUBLIC members
	this.title = (title == undefined) ? "No Title" : title;
	this.name = id;
	this.objName = "#"+this.name;
	this.divObject = this.pageElement.divObject;
	this.status = null;
	
	this.element = null;
	this.element_body = null;
	this.element_body_wrapper = null;
	this.element_message = null;
	this.element_titlebar = null;
	this.element_toggle = null;
	this.element_close = null;
	this.tabsElement = null;

	this.updateListeners = [];
	this.updateListenerNames = [];	
	this.origContainer = null;
	this.closed = true;
	this.collapsed = false;
	this.width = -1;
	this.hasError = false;
	this.isRendered = false;				// set this to true if the task is rendered on load versus delayed loading then false
	this.clearCurrentToolItem = false;

	this.setClearCurrentToolItem = function(flag) {
		this.clearCurrentToolItem = (flag != null) ? flag : false;
	}
	
	this.resetCurrentToolItem = function() {
		if(this.clearCurrentToolItem) {
			var map = EsriControls.maps["map1"];
        	if(map) {
        		map.resetToolItem();
        	}
        }
	}
	
	/**
	 * SHOW sets the display property of the taskwindow to 'block' and calculates its (new) position
	 */
	this.show = function() {
		this.closed = false;			// set the closed flag to false
		this.center();					// move to front and relative offset to last opened window (could be sth. different)
		this.setWidth();
		this.element.show(); 			// using jquery to set display: block;
	}
	
	/**
	 * HIDE sets the display property of the taskwindow to 'none'
	 */
	this.hide = function() {
		this.hideMessage();				// hide all previously created error messages
		this.closed = true;				// set the closed flag to true
		this.element.hide(); 			// using jquery to set display: none;
		this.resetCurrentToolItem()		// reset current tool in application to the previousely selected/default on the toolbar 
	}
	
	/**
	 * TOFRONT sets the current z-index of the taskwindow to the fore-most (highest) value
	 */
	this.toFront = function(zIndex) {
		// disregard the zIndex parameter and use internal zIndex instead
		this.zIndex = zIndexAll + 1;
		this.element.css("z-index",this.zIndex);
		zIndexAll = this.zIndex;
	}
	
	/**
	 * TOBACK sets the current z-index of the taskwindow to zero
	 */
	this.toBack = function() {
		// dummy; only moves the window to the 0 position
		this.element.css("z-index",0);
	}
	
	/**
	 * MOVETO will adjust the left (x) and top (y) position of the taskwindow
	 */
	this.moveTo = function(x,y) {
		if (this.movable) {
			this.element.css("left",x+"px");
			this.element.css("top",y+"px");
		}
	}
	
	/**
	 * RESIZE adjusts the width and height of the taskwindow
	 */
	this.resize = function(width,height) {
		// resize anyway (whether or not the resizable flag is true or false
		//if (this.resizable) {
			var body_wrapper_height = height - parseInt(this.element_titlebar.css("height"));
			this.element_body_wrapper.css("width",width+"px");
			this.element_body_wrapper.css("height",body_wrapper_height+"px");
			this.element_body.css("width",width+"px");
			this.element_body.css("height",body_wrapper_height+"px");
			this.element.css("width",width+"px");
			this.element.css("height",height+"px");
		//}
	}

	/**
	 * SETWIDTH adjusts the width of the taskwindow
	 */
	this.setWidth = function(width) {
		// if no width is set then take the existing width of the taskwindow 
		if (width == null) {
			width = this.width;
		}
		if (width > 0) {
			// adjust the width of important taskwindow elements
			this.element_body_wrapper.css("width",width+"px");
			this.element_body.css("width",width+"px");
			this.element.css("width",width+"px");
		}
	}
	
	/**
	 * UPDATE is called after callback has created new content (of the existing element)
	 */
	this.update = function() {
		// ok, this is a terrible hack; 
		// a fake image appears before the content is loaded; 
		// this is needed for the loading indicator to appear
		// once the 'fake' content is replaced we can do the real update
		if (this.isRendered || !$("#"+pageElement.divId+" img").attr("name")) {
			//this.hideMessage();
			this.initTabs();
			this.hideLoading();
		}
		/*
		if (this.resizable) {
			this.fit();
		}
		*/
	}
	
	/**
	 * FIT will adjust the size of the taskwindow to the max width of its included tables
	 */
	this.fit = function() {
		// if task window is a floating window -> adjust width (otherwise: width=100%)
		if (this.isFloatingWindow) {
			if (!this.closed && this.width < 0) {
				var maxWidth = 0;
				// loop through all the tables in the task and find the maximum width (assuming table is used to wrap the task this will find our ideal width)
				$(this.objName+" table").each(function (i) {
					if (this.clientWidth > maxWidth) {
						maxWidth = this.clientWidth;
					}
				});
				// make it 10 pixel wider than calculated
				if (maxWidth > 0) {
					maxWidth = maxWidth + 10;
					// add smooth animation
					this.element.animate({width: maxWidth+"px"}, "fast");
					this.width = maxWidth;
				}
			} 
			else {
				this.element.css("width", this.width+"px");
			} 
		} else {
			this.element.css("width", "100%");
		}
		$(this.objName).bgiframe({top:'-1px'});
	}
	
	/**
	 * CENTER has no functionality as of yet
	 */
	this.center = function() {
		if (this.isFloatingWindow) {		// only position the window when it is a floating window (otherwise it is docked somewhere)
			this.toFront(0);				// always place the window on top when showing
			if (this.lastPosX < 0 && this.lastPosY < 0) {
				lastPosXAll -= 15;			// decrease the left position for all windows 
				lastPosYAll += 15;			// increase the top position for all windows
				if (lastPosXAll < 50) {		// reset when max left position reached
					lastPosXAll = 300;
					lastPosYAll = 100;
				}
				if (lastPosYAll > 250) {	// reset when max top position reached
					lastPosYAll = 100;
				}
				this.lastPosX = lastPosXAll;
				this.lastPosY = lastPosYAll;
				this.moveTo(lastPosXAll, lastPosYAll);
			}
		}
	}
	
	/**
	 * Initialize the floating panel
	 *
	 * build the container HTML that surrounds the content
	 * initialize jquery handles required to access the various panel elements
	 * add action handlers to elements
	 */
	this.init = function(container) {
		
	    this.origContainer = (!container) ? document.body : container;
	
		//---------------------------------------------------
		// floating panel container
		var fp_window_container = document.createElement("div");
		fp_window_container.id = this.name;
		fp_window_container.className = (this.isFloatingWindow) ? "jitk-floating-panel-window-container" : "jitk-floating-panel-window-container-inside";
	
		//---------------------------------------------------
		// floating panel window
		var fp_window = document.createElement("div");
		fp_window.id = this.name+"_window";
		fp_window.className = "jitk-floating-panel-window";
		
		//---------------------------------------------------
		// titlebar container
		var fp_titlebar = document.createElement("div");
		fp_titlebar.id = this.name+"_titlebar";
		fp_titlebar.className = "jitk-floating-panel-titlebar";
		if (!this.isFloatingWindow) {
			fp_titlebar.style.display = "none";
		}
		
		//---------------------------------------------------
		// title inside the titlebar
		var fp_titlebar_text = document.createElement("div");
		fp_titlebar_text.className = "jitk-floating-panel-titlebar-text";
		fp_titlebar_text.appendChild(document.createTextNode(this.title));
		fp_titlebar.appendChild(fp_titlebar_text);
		
		//---------------------------------------------------
		// buttons
		var fp_titlebar_button;
		var fp_titlebar_button_anchor;
		// buttons div
		fp_titlebar_button = document.createElement("div");
		fp_titlebar_button.className = "jitk-floating-panel-titlebar-button";
		// collapse button
		fp_titlebar_button_anchor = document.createElement("a");
		fp_titlebar_button_anchor.className = "collapse";
		fp_titlebar_button_anchor.id = this.name+"_toggle";
		fp_titlebar_button_anchor.href = "#";
		fp_titlebar_button_anchor.appendChild(document.createTextNode("\u00a0"));
		fp_titlebar_button.appendChild(fp_titlebar_button_anchor);
		// close button		
		fp_titlebar_button_anchor = document.createElement("a");
		fp_titlebar_button_anchor.className = "close";
		fp_titlebar_button_anchor.id = this.name+"_close";
		fp_titlebar_button_anchor.href = "#";
		fp_titlebar_button_anchor.appendChild(document.createTextNode("\u00a0"));
		fp_titlebar_button.appendChild(fp_titlebar_button_anchor);
		fp_titlebar.appendChild(fp_titlebar_button);
		
		// append the titlebar container to the floating panel window
		fp_window.appendChild(fp_titlebar);
	
		//---------------------------------------------------
		// body wrapper
		var fp_body_wrapper = document.createElement("div");
		fp_body_wrapper.id = this.name+"_body_wrapper";
		fp_body_wrapper.className = "jitk-floating-panel-window-body-wrapper";
	
		//---------------------------------------------------
		// body	
		var fp_body = document.createElement("div");
		fp_body.id = this.name+"_body";
		fp_body.className = "jitk-floating-panel-window-body";
	
		//---------------------------------------------------
		// message
		var fp_message = document.createElement("div");
		fp_message.id = this.name+"_message";
		fp_message.className = "jitk-message";
		fp_body.appendChild(fp_message);

		//---------------------------------------------------
		// fake body (loading image)
		if (!this.isRendered) {
			var fp_body_content = $("#"+this.pageElement.divId);
			if (!fp_body_content) {
				fp_body_content = document.createElement("div");
				fp_body_content.id = this.pageElement.divId;
				var fp_body_content_blank = document.createElement("img");
				fp_body_content_blank.setAttribute("src", "images/blank.gif");
				fp_body_content_blank.setAttribute("width", "300");
				fp_body_content_blank.setAttribute("height", "250");
				fp_body_content_blank.setAttribute("alt", "");
				fp_body_content.appendChild(fp_body_content_blank);
				fp_body.appendChild(fp_body_content);		
			} else {
				fp_body_content.html("<img src='images/blank.gif' name='blank' width='300' height='250' alt='' />");
			}
		}
		
		//---------------------------------------------------
		// add the content to the body (content as rendered by XSL task framework and passed in as pageElement)
		fp_body.appendChild(this.divObject);
	
		// add body to to body wrapper
		fp_body_wrapper.appendChild(fp_body);
	
		// add body wrapper to to floating panel window
		fp_window.appendChild(fp_body_wrapper);
		
		// add floating panel window to the floating panel container
		fp_window_container.appendChild(fp_window);	
		
		// add floating panel container to the MAIN container 
		// (could be the html body or any other ueber-element)
		this.origContainer.appendChild(fp_window_container);
		
		//---------------------------------------------------
		// initialize the jquery handles used to access the various elements of the floating panel
		this.element = $(this.objName);
		this.element_body = $(this.objName+"_body");
		this.element_body_wrapper = $(this.objName+"_body_wrapper");
		this.element_message = $(this.objName+"_message");
		this.element_titlebar = $(this.objName+"_titlebar");
		this.element_toggle = $(this.objName+"_toggle");
		this.element_close = $(this.objName+"_close");

		//this.element.css("width","220px");
		//this.element.css("height","180px");
	
		//---------------------------------------------------
		// initialize the tabs
		this.initTabs();
		
		//---------------------------------------------------
		// initialize the tools of the floating panel (toggle, close, drag)
		this.initTools();
		
		if (!this.isRendered) {
			this.showLoading();
		}
	}
}

JitkWindow.prototype.closeHandler = function() {
	
	if(this.name == 'win_EsriTaskCell_labelRedliningTask' || this.name == 'win_EsriTaskCell_shapeRedliningTask') {
		var colorChooserWin = taskWindowManager.windows["colorChooserWin"];
		if(colorChooserWin && !colorChooserWin.closed) {
			colorChooserWin.hide();
		}
	}
	
	if(this.name == 'win_EsriTaskCell_SelectionSymbologyTask') {
		var colorChooserWin = taskWindowManager.windows["jitkSymbologyColorChooserWin"];
		if(colorChooserWin && !colorChooserWin.closed) {
			colorChooserWin.hide();
		}
	}
	
	return true;
}

/**
 * Messages (error, success, etc.)
 */
JitkWindow.prototype.showMessage = function(type, text) {
	var cssClass = "";
	
	switch (type) {
		case "info":
		case "information":
			cssClass = "information";
			break;
		case "success":
			cssClass = "success";
			break;
		case "question":
			cssClass = "question";
			break;
		case "warning":
		case "warn":
			cssClass = "warning";
			break;
		case "error":
		case "fail":
		case "failure":
		default:
			cssClass = "error";
			break;
	}
	
	if(text && text.length > 0) {
		// convert to array
		if(text.constructor.toString().indexOf("Array") == -1) {
			text = new Array(text);
		}
	
		var outputText = "<div class=\"" + cssClass + "\"><ul>";
		for(i=0; i < text.length; i++) {
			outputText += "<li>" + text[i] + "</li>";
		}
		outputText += "</ul></div>";
		
		var el = this.element_message;
		if(el.html() == "") {
			el.html(outputText);
			el.slideDown(this.animationSpeed);
		} else {
			el.slideUp(50, function() {
				el.html(outputText);
			}).slideDown(this.animationSpeed);
		}
		
	} else {
		this.hideMessage();
	} 
}

JitkWindow.prototype.hideMessage = function() {
	var el = this.element_message;
	el.slideUp(50, function() {
		el.html("");
	});
}

JitkWindow.prototype.error = function(text) { this.showMessage('error', text); }
JitkWindow.prototype.failure = function(text) { this.showMessage('error', text); }
JitkWindow.prototype.fail = function(text) { this.showMessage('error', text); }
JitkWindow.prototype.warning = function(text) { this.showMessage('warning', text); }
JitkWindow.prototype.warn = function(text) { this.showMessage('warning', text); }
JitkWindow.prototype.information = function(text) { this.showMessage('information', text); }
JitkWindow.prototype.info = function(text) { this.showMessage('information', text); }
JitkWindow.prototype.success = function(text) { this.showMessage('success', text); }
JitkWindow.prototype.question = function(text) { this.showMessage('question', text); }

/**
 * Loading Indicator
 */
JitkWindow.prototype.submit = function(element) {
	element.disabled = true;

	// show the loading indicator of the task window
	this.showLoading();
	
	// hide all messages (will be populated on server again if error still exists)
	this.hideMessage();
	
	// set the currently selected tab if tabs are used
	if (this.tabsElement != null) {
		this.setSelectedTab(this.tabsElement.data('selected.tabs'));
	}
}
JitkWindow.prototype.showLoading = function() {
	// IE work around to hide form elements that would shine through
	var self = this;
	if ($.browser.msie) {
		jQuery.each(jQuery.browser, function(i, val) {
			if (i=="msie" && parseInt(jQuery.browser.version.substr(0,3),10)<7) {
				$(self.objName+" select").each(function (i) {
					$(this).css("visibility", "hidden");
				});
			}
		});
	}
	this.element_body.fadeTo(1, 0.25);
}
JitkWindow.prototype.hideLoading = function() {
	var self = this;
	if ($.browser.msie) {
		jQuery.each(jQuery.browser, function(i, val) {
			if (i=="msie" && parseInt(jQuery.browser.version.substr(0,3),10)<7) {
				$(self.objName+" select").each(function (i) {
					$(this).css("visibility", "visible");
				});
				// apply PNG fix to newly rendered content
				$(self.objName+" img").ifixpng();
			}
		});
	}
	this.element_body.fadeTo(1, 1);
}

JitkWindow.prototype.setSelectedTab = function(selectedTab) {
	if (this.tabsElement != null) {
		jitkTaskWindowSelectedTabs[this.divObject.id] = parseInt(selectedTab,10);
	}
}

JitkWindow.prototype.initTabs = function() {
	// initialize the tabs
	var self = this;
	
	selectedIndex = (jitkTaskWindowSelectedTabs[this.divObject.id] != null) ? jitkTaskWindowSelectedTabs[this.divObject.id] : 0;
	
	this.tabsElement = $("#"+this.divObject.id+" > ul").tabs({selected:selectedIndex});
	/*
	// cannot use this event handler because esri_core cannot process it
	.bind("tabsshow", function(event, ui) {
		self.fit();
		return false;
	});
	*/
}
JitkWindow.prototype.initTools = function() {
	/* window toggle expand/collapse */
	var self = this;
	var animationSpeed = this.animationSpeed;
	if (this.collapsable) {
		var el_body_wrapper = this.element_body_wrapper;
		var el_main = this.element;
		var el_body = this.element_body;
		this.element_toggle.show();
		this.element_toggle.toggle(
			function () {
				var el = $(this);
				el_main.css("height","");
				//el_body.css("height","");
				el_body_wrapper.slideUp(50, function() {
					self.collapsed = false;
					el.attr("class", "expand");
				});
			},
			function () {
				var el = $(this);
				el_body_wrapper.slideDown(animationSpeed, function() {
					self.collapsed = true;
					el.attr("class", "collapse");
				});
			}
		);
	} else {
		this.element_toggle.hide();		// hide the toggle button
	}

	/* window close */
	if (this.closable) {
		var el = this.element;
		this.element_close.show();
		this.element_close.click(function(){
			var width = el.css("width");
			//var height = el.css("height"); // replaced with "auto"
			el.animate({ 
				width: "0px",
				height: "0px"
			}, animationSpeed, "", function() {
				//el.hide();
				self.hide();
				el.css("width",width);
				el.css("height","auto");
			});
			
			self.closed = true;
			
			//$("body").trigger("jitkCustomEventTaskWindowClose", [ self ]);
			if (self.closeHandler != null) {
				self.closeHandler(new JitkWindowEventArgs(self.name));
			}
			
			return false;
		});
	} else {
		this.element_close.hide();		// hide the close button	
	}

	/* window drag */	
	var el = this.element;
	el.draggable();
	el.draggable("disable");
	if (this.movable) {
		$(".jitk-floating-panel-titlebar").css("cursor","move");
	} else {
		$(".jitk-floating-panel-titlebar").css("cursor","");
	}
	this.element_titlebar.mouseout(function(){
		if (self.movable) {
			el.draggable("disable");
		}
	}).mouseover(function() {
		self.show();
		if (self.movable) {
			el.draggable("enable");
		}
	});
}


JitkWindow.prototype.setWindowManager = function(wm) {
	this.windowMgr = wm;
}

JitkWindow.prototype.addUpdateListener = function(name, listener) {
  if (this.updateListenerNames.indexOf(name) == -1) this.updateListenerNames.push(name);
  this.updateListeners[name] = listener;
}

JitkWindow.prototype.removeUpdateListener = function(name) {
  var index = this.updateListenerNames.indexOf(name);
  if (index != -1) {
    this.updateListenerNames.splice(index, 1);
    this.updateListeners[name] = null;
  }
}

//JitkWindow.prototype.toggleVisibility = function() { this.element.css("display")=="none" ? this.show() : this.hide(); }
JitkWindow.prototype.toggleVisibility = function() { this.show();this.fit(); }

JitkWindow.prototype.jitkGetGlobalZIndex = function() {
	return zIndexAll;
}
