/**
 * This file must be included to support popup windows. You can instantiate the PopupWindow class by giving the ID of the body,
 * the position and size and the name / title of the window. The positions and size may ONLY BE IN PIXELS 
 * (p.h. "new PopupWindow('id', '100px', '200px', '300px', '400px', 'A nice popup').
 * <b>Note! This is not completely reliable in IE 6</b>.
 * 
 * @version 2011-01-04
 * @author <a href="mailto:r.tennapel@griponservice.nl?SUBJECT=popupwindow.js">R. ten Napel, ing.</a>
 **/

/**
 * The popup window class handles popup functionality.
 * Warning! NEVER USE % IN X, Y, W, H!
 * 
 * @param id					The ID of the body in the window.
 * @param x						The X-offset, if set to NULL, the position will be horizontal-centered.
 * @param y						The Y-offset, if set to NULL, the position will be vertical-centered.
 * @param w						The width.
 * @param h						The height.
 * @param title					The title.
 * @param transparency			The transparency level of filter layer, if not set, std. 50% will be used.
 **/
PopupWindow = function(id, x, y, w, h, title, transparency) {
	this.id = id;
	this.x = (x == null) ? ((GlobalKit.screenWidth() - parseInt(w)) / 2) + "px" : x;
	this.y = (y == null) ? ((GlobalKit.screenHeight() - parseInt(h)) / 2) + "px" : y;
	this.w = w;
	this.h = h;
	this.title = title;
	this.transparency = (transparency == null) ? 50 : transparency;
	this.state = "normal";
	
	// Set the minimum dimensions for minimization:
	this.minWidth = 200;
	this.minHeight = 80;
	
	// Initialize everything:
	this.init();
};

/**
 * The internal list of popup windows.
 **/
PopupWindow.windows = [];

/**
 * The minimized columns & rows.
 **/
PopupWindow.minimizedCols = 6;
PopupWindow.minimizedRows = 2;

/**
 * Minimize all windows.
 **/
PopupWindow.minimizeAll = function() {
	for (var i = 0; i < PopupWindow.windows.length; i++) {
		PopupWindow.windows[i].minimize();
	}
};

/**
 * Retrieve the amount of windows that are minimized.
 * 
 * @return						The amount of windows that are minimized.
 **/
PopupWindow.minimized = function() {
	var pos = 0;
	
	// Check each window:
	for (var i = 0; i < PopupWindow.windows.length; i++) {
		if (PopupWindow.windows[i].state == "min") {
			pos++;
		}
	}
	
	return pos;
};

/**
 * Re-order all minimized windows.
 **/
PopupWindow.orderMinimized = function() {
	var pos = 0;
	
	// Move all minimized windows:
	for (var i = 0; i < PopupWindow.windows.length; i++) {
		if (PopupWindow.windows[i].state == "min") {
			var w = PopupWindow.windows[i].minWidth;
			var h = PopupWindow.windows[i].minHeight;
			var x = (pos % PopupWindow.minimizedCols) * w;
			var y = GlobalKit.screenHeight() - h - (h * Math.floor(pos / PopupWindow.minimizedCols));
			
			// Start animation:
			$(PopupWindow.windows[i].container).moveTo(x, y, 500, Tween.ease, 30).resizeTo(w, h, 500, Tween.ease, 30);
			
			pos++;
		}
	}
};

/**
 * Create a new popup window instance.
 * 
 * @param id					The ID of the body in the window.
 * @param x						The X-offset, if set to NULL, the position will be horizontal-centered.
 * @param y						The Y-offset, if set to NULL, the position will be vertical-centered.
 * @param w						The width.
 * @param h						The height.
 * @param title					The title.
 * @param transparency			The transparency level of filter layer, if not set, std. 50% will be used.
 * 
 * @return						This window.
 **/
PopupWindow.create = function(id, x, y, w, h, title, transparency) {
	return new PopupWindow(id, x, y, w, h, title, transparency);
};

/**
 * Fix the styling for irritating Opera absolute bottom / right bug.
 **/
PopupWindow.prototype.fixOpera = function() {
	$(this.container).setStyle("display", "table");
};

/**
 * Retrieve the adapted scroller height.
 * 
 * @param height				The window height.
 **/
PopupWindow.prototype.getScrollerHeight = function(height) {
	return (parseInt(height) - 12 - 32 - 8) + "px";
};

/**
 * Initialize the complete window.
 **/
PopupWindow.prototype.init = function() {
	// Only add transparency layer when not false:
	if (this.transparency != false) {
		this.filter = this.createFilter(this.transparency);
	}
	
	// Create everything:
	this.title = this.createTitle(this.title);
	this.btnMin = this.createBtnMin();
	this.btnMax = this.createBtnMax();
	this.btnClose = this.createBtnClose();
	this.buttons = this.createButtons();
	this.body = this.createBody(this.id);
	this.scroller = this.createScroller();
	this.container = this.createContainer(this.x, this.y, this.w, this.h);
	
	// Fix the container styling for Opera:
	if (navigator.userAgent.contains("Opera")) {
		this.fixOpera();
	}
	
	// Add this new window to the internal list:
	PopupWindow.windows.add(this);
};

/**
 * Create the filter layer.
 * 
 * @param transparency			The transparency level of the filter.
 * 
 * @return						The created filter element.
 **/
PopupWindow.prototype.createFilter = function(transparency) {
	// Create new element:
	var filter = document.createElement("DIV");
	filter.window = this;
	
	// Set the filter styling:
	(GlobalKit.browser().contains("MSIE 6")) ? $(filter).setStyle("position", "absolute").setStyle("width", "100%") : $(filter).setStyle("position", "fixed").setStyle("width", "200%");
	$(filter).css({
			backgroundColor: "#000000",
			left: "0px",
			top: "0px",
			height: "100%"
	}).setTransparency(transparency);
	
	// Add the filter:
	document.body.appendChild(filter);
	
	return filter;
};

/**
 * Create the title block for the window.
 * 
 * @param text					The title.
 * 
 * @return						The created title block.
 **/
PopupWindow.prototype.createTitle = function(text) {
	// Create new element:
	var title = document.createElement("DIV");
	title.window = this;
	$(title).addClass("title").append(text);
	
	return title;
};

/**
 * Create the minimize-button.
 * 
 * @return						The created minimize-button.
 **/
PopupWindow.prototype.createBtnMin = function() {
	// Create new element:
	var min = document.createElement("A");
	min.window = this;
	min.href = "Javascript:void(0);";
	min.setAttribute("href", min.href);
	$(min).addClass("btnMin").on("click", function() { this.window.minimize(); }).on("dblclick", function() { PopupWindow.minimizeAll(); });
	
	return min;
};

/**
 * Create the maximize-button.
 * 
 * @return						The created maximize-button.
 **/
PopupWindow.prototype.createBtnMax = function() {
	// Create new element:
	var max = document.createElement("A");
	max.window = this;
	max.href = "Javascript:void(0);";
	max.setAttribute("href", max.href);
	$(max).on("click", function() {
		if (this.window.state == "normal") {
			this.window.maximize();
		} else {
			this.window.normalize();
		}
	}).addClass("btnMax");
	
	return max;
};

/**
 * Create the close-button.
 * 
 * @return						The created close-button.
 **/
PopupWindow.prototype.createBtnClose = function() {
	// Create new element:
	var close = document.createElement("A");
	close.window = this;
	//close.href = "Javascript:void(0);";		// Previous code doesn't work in IE (it will open a new page called [object], commenting this code out works
	//close.setAttribute("href", close);		// Previous code doesn't work in IE (it will open a new page called [object], commenting this code out works
	$(close).addClass("btnClose").on("click", function() { this.window.hide(); });
	
	return close;
};

/**
 * Create the button block.
 * 
 * @return						The created button block.
 **/
PopupWindow.prototype.createButtons = function() {
	// Create new element:
	var buttons = document.createElement("DIV");
	buttons.window = this;
	$(buttons).addClass("buttons");
	
	// Add the buttons:
	buttons.appendChild(this.btnMin);
	buttons.appendChild(this.btnMax);
	buttons.appendChild(this.btnClose);
	
	return buttons;
};

/**
 * Create the body block.
 * 
 * @param id					The ID to assign to the body block.
 * 
 * @return						The created body block.
 **/
PopupWindow.prototype.createBody = function(id) {
	// Create new element:
	var body = document.createElement("DIV");
	body.window = this;
	body.id = id;
	$(body).addClass("body");
	
	// Override the destroy function of the body:
	body.destroy = function() {
		this.window.destroy();
	};
	
	// Override the show function of the body:
	body.show = function() {
		this.window.show();
	};
	
	// Override the hide function of the body:
	body.hide = function() {
		this.window.hide();
	};
	
	// Override the setTitle function of the body:
	body.setTitle = function(title) {
		this.window.setTitle(title);
	};
	
	// Override the makeDraggable function of the body:
	body.makeDraggable = function() {
		this.window.makeDraggable();
	};
	
	// Override the makeResizable function of the body:
	body.makeResizable = function() {
		this.window.makeResizable();
	};
	
	return body;
};

/**
 * Create the scroller block.
 * 
 * @return						The created scroller block.
 **/
PopupWindow.prototype.createScroller = function() {
	// Create new element:
	var scroller = document.createElement("DIV");
	scroller.window = this;
	scroller.id = this.id + "_scroller";
	$(scroller).addClass("scroller");
	
	// Add the body:
	scroller.appendChild(this.body);
	
	return scroller;
};

/**
 * Create the container to hold the frame.
 * 
 * @param x						The X-offset.
 * @param y						The Y-offset.
 * @param w						The width.
 * @param h						The height.
 * 
 * @return						The created container.
 **/
PopupWindow.prototype.createContainer = function(x, y, w, h) {
	// Create the container:
	var container = document.createElement("DIV");
	container.window = this;
	container.id = this.id + "_container";
	
	// Create top left:
	var cell = document.createElement("DIV");
	$(cell).addClass("topLeft");
	container.appendChild(cell);
	
	// Create top:
	cell = document.createElement("DIV");
	cell.window = this;
	$(cell).addClass("top");
	cell.appendChild(this.title);
	cell.appendChild(this.buttons);
	container.appendChild(cell);
	
	// Create top right:
	cell = document.createElement("DIV");
	$(cell).addClass("topRight");
	container.appendChild(cell);
	
	// Create left:
	cell = document.createElement("DIV");
	$(cell).addClass("left");
	container.appendChild(cell);
	
	// Create center:
	container.appendChild(this.scroller);
	
	// Create righ:
	cell = document.createElement("DIV");
	$(cell).addClass("right");
	container.appendChild(cell);
	
	// Create bottom left:
	cell = document.createElement("DIV");
	$(cell).addClass("bottomLeft");
	container.appendChild(cell);
	
	// Create bottom:
	cell = document.createElement("DIV");
	$(cell).addClass("bottom");
	container.appendChild(cell);
	
	// Create bottom right:
	cell = document.createElement("DIV");
	$(cell).addClass("bottomRight");
	container.appendChild(cell);
	
	// Set the container styling:
	(GlobalKit.browser().contains("MSIE 6")) ? $(container).setStyle("position", "absolute") : $(container).setStyle("position", "fixed");
	$(container).css({
			left: x,
			top: y,
			width: w,
			height: h
		}).addClass("popupWindow");
	
	// Add the container to the document:
	document.body.appendChild(container);
	
	return container;
};

/**
 * Show the window.
 * 
 * @return						This window.
 **/
PopupWindow.prototype.show = function() {
	// Set the state:
	this.state = "normal";
	
	$(this.filter, this.container).show();
	
	// Fix the container styling for Opera:
	if (navigator.userAgent.contains("Opera")) {
		this.fixOpera();
	}
	
	return this;
};

/**
 * Hide the window.
 * 
 * @return						This window.
 **/
PopupWindow.prototype.hide = function() {
	// Set the state:
	this.state = "hidden";
	
	// Hide the window (& filter):
	$(this.filter, this.container).hide();
	
	// Fix the container styling for Opera:
	if (navigator.userAgent.contains("Opera")) {
		this.fixOpera();
	}
	
	// Re-order all minimized windows:
	PopupWindow.orderMinimized();
	
	return this;
};

/**
 * Remove the window from the DOM.
 **/
PopupWindow.prototype.destroy = function() {
	$(this.container).destroy();
	
	// Also remove the window from the internal list:
	PopupWindow.windows.remove(this);
	
	// Re-order all minimized windows:
	PopupWindow.orderMinimized();
};

/**
 * Set the title of this window.
 * 
 * @param title					The title to set.
 * 
 * @return						This window.
 **/
PopupWindow.prototype.setTitle = function(title) {
	$(this.title).update(title);
	
	return this;
};

/**
 * Make the window draggable.
 * 
 * @return						This window.
 **/
PopupWindow.prototype.makeDraggable = function() {
	// Create a manual grasp handler for the top DIV which holds the title & buttons:
	var graspHandler = function(dragObject, pos) {
		// Store the original settings:
		dragObject.original = {
				position: $(dragObject.element).getStyle("position"),
				left: $(dragObject.element).getStyle("left"),
				top: $(dragObject.element).getStyle("top")
			};
		
		// Prepare the element for dragging:
		$(dragObject.element).addClass("dragging").setStyle("position", "absolute");
		
		// Prepare the window wrapper:
		$(dragObject.element.parentNode.window.container).addClass("dragging");
		
		// Store the drag offset:
		var box = $(dragObject.element).getBox();
		dragObject.offset.x = pos.x - box.x;
		dragObject.offset.y = pos.y - box.y;
	};
	
	// Create a manual drag handler for the top DIV which holds the title & buttons:
	var dragHandler = function(dragObject, pos) {
		var element = dragObject.element.parentNode;
		
		// Retrieve the position of the element:
		var x = (pos.x - dragObject.offset.x);
		var y = (pos.y - dragObject.offset.y);
		
		// Update the position if the drag object is outside the screen:
		var box = $(element).getBox();
		if (x < 0) {
			x = 0;
		} else if ((x + box.w) > GlobalKit.screenWidth()) {
			x = GlobalKit.screenWidth() - box.w;
		}
		if (y < 0) {
			y = 0;
		} else if ((y + box.h) > GlobalKit.screenHeight()) {
			y = GlobalKit.screenHeight() - box.h;
		}
		
		// Set the window coördinates if not minimized:
		if (element.window.state != "min") {
			element.window.x = x + "px";
			element.window.y = y + "px";
		}
		
		// Set the position:
		$(element).css({
			left: x + "px",
			top: y + "px"
		});
	};
	
	// Create a manual release handler for the top DIV which holds the title & buttons:
	var releaseHandler = function(dragObject) {
		// Restore the original settings:
		$(dragObject.element).removeClass("dragging").css({
				position: dragObject.original.position,
				left: dragObject.original.left,
				top: dragObject.original.top
			});
		
		// Restore the window wrapper:
		$(dragObject.element.parentNode.window.container).removeClass("dragging");
		
		// Clear the basics:
		dragObject.original = { position: null, x: 0, y: 0 };
		dragObject.offset = { x: 0, y: 0 };
		
		// If a drop object is tracked, drop this drag object into it:
		if (Dragdropper.dropObject != null) {
			Dragdropper.dropObject.drop(dragObject);
		}
	};
	
	// Make this window draggable:
	Dragdropper.makeDraggable(this.container.children[1], null, graspHandler, dragHandler, releaseHandler);
	
	return this;
};

/**
 * Make the window resizable.
 * 
 * @return						This window.
 */
PopupWindow.prototype.makeResizable = function() {
	// Make this window resizable:
	Dragdropper.makeResizable(this.container);
	
	return this;
};

/**
 * Minimize the window.
 **/
PopupWindow.prototype.minimize = function() {
	// Don't minimize if already minimized:
	if (this.state == "min") {
		return;
	}
	
	// Re-order all minimized windows:
	PopupWindow.orderMinimized();
	
	// Retrieve how much windows are minimized:
	var pos = PopupWindow.minimized();
	
	// Set the state of this window:
	this.state = "min";
	
	// Start the animation (don't make the minimize height too small!):
	var w = this.minWidth;
	var h = this.minHeight;
	var x = (pos % PopupWindow.minimizedCols) * w;
	var y = GlobalKit.screenHeight() - h - (h * Math.floor(pos / PopupWindow.minimizedCols));
	$(this.container).moveTo(x, y, 1000, Tween.ease, 30).resizeTo(w, h, 1000, Tween.ease, 30);
};

/**
 * Set the position and size of the window to the original position.
 **/
PopupWindow.prototype.normalize = function() {
	// Don't normalize if already normalized:
	if (this.state == "normal") {
		return;
	}
	
	this.state = "normal";
	
	// Start the animation:
	$(this.container).moveTo(this.x, this.y, 1000, Tween.ease, 30).resizeTo(this.w, this.h, 1000, Tween.ease, 30);
	
	// Re-order all minimized windows:
	PopupWindow.orderMinimized();
};

/**
 * Maximize the window.
 **/
PopupWindow.prototype.maximize = function() {
	// Don't maximize if already maximized:
	if (this.state == "max") {
		return;
	}
	
	this.state = "max";
	
	// Start the animation:
	$(this.container).moveTo(0, 0, 1000, Tween.ease, 30).resizeTo(GlobalKit.screenWidth(), GlobalKit.screenHeight(), 1000, Tween.ease, 30);
	
	// Re-order all minimized windows:
	PopupWindow.orderMinimized();
};

/**
 * Place the window at the exact center of the screen.
 **/
PopupWindow.prototype.centerScreen = function() {
	// Calculate new offset:
	this.x = ((GlobalKit.screenWidth() - parseInt(this.w)) / 2) + "px";
	this.y = ((GlobalKit.screenHeight() - parseInt(this.h)) / 2) + "px";
	
	// Apply the new position and ensure fixed:
	$(this.container).css({
			position: "fixed",
			left: this.x,
			top: this.y,
			width: this.w,
			height: this.h
		});
};
