// PositionedWindow positions a new window somewhere on the screen relative to the current window
// Mainly useful for popup windows of varying stripes; a single instance of the class can manage numerous links
var PositionedWindow = new Class({
	Implements: [Options, Events],
	Binds: ['addLink'],
	options: {
		width: 640,
		height: 480,
		edge: false,
		position: 'center',
		windowFeatures: 'location,menubar,resizable,scrollbars,status,toolbar',
		focus: true,
		reuseWindow: false
	},
	
	// Class variables
	win: null,
	
	initialize: function(trigger, options) {
		this.setOptions(options);
		
		// Parse the position options
		this.options.edge = this.parsePosition(this.options.edge);
		this.options.position = this.parsePosition(this.options.position);
		
		// Add click events to the trigger
		// Trigger can be an element/ID, a selector, or an array of elements
		var triggerType = $type(trigger);
		if (triggerType == 'element' || document.id(trigger)) {
			this.addLink(trigger);
		} else if (triggerType == 'array') {
			// Previously gathered array of elements
			trigger.each(function(el) {
				this.addLink(el);
			}, this);
		} else if (triggerType == 'string') {
			// Otherwise we assume it's a selector
			document.getElements(trigger).each(function(el) {
				this.addLink(el);
			}, this);
		}
	},
	
	parsePosition: function(option) {
		// This is lifted straight out of Element.Position; formerly fixValue()
		//upperRight, bottomRight, centerRight, upperLeft, bottomLeft, centerLeft
		//topRight, topLeft, centerTop, centerBottom, center
		if ($type(option) != 'string') return option;
		option = option.toLowerCase();
		var val = {};
		if (option.test('left')) val.x = 'left';
		else if (option.test('right')) val.x = 'right';
		else val.x = 'center';
		if (option.test('upper') || option.test('top')) val.y = 'top';
		else if (option.test('bottom')) val.y = 'bottom';
		else val.y = 'center';
		return val;
	},
	
	open: function(event) {
		// `this` here is the element that was clicked, which has a `positionedWindow` element we can use to access the object
		// By doing this, we can use fireEvent if necessary to trigger this
		if ($chk(event)) event.stop();
		
		var self = this.positionedWindow;
		
		// Init basic positioning info for the main window and screen
		var fromLeft = 0, fromTop = 0;
		var pos = new ScreenDimensions();
		
		// Determine reference points for the new window; defaults to center
		var ref = {x: 0, y: 0};
		switch(self.options.position.x) {
			case 'center':
				ref.x = self.options.width / 2;
				break;
			case 'right':
				ref.x = self.options.width;
				break;
		}
		switch(self.options.position.y) {
			case 'center':
				ref.y = self.options.height / 2;
				break;
			case 'bottom':
				ref.y = self.options.height;
				break;
		}
		// Determine edge point
		if (!self.options.edge){
			// No edge defined, so we'll do it relative to the screen edge
			var edge = {x: 0, y: 0};
			self.options.edge = self.options.position;
			switch(self.options.edge.x) {
				case 'center':
					edge.x = pos.screen.width / 2;
					break;
				case 'right':
					edge.x = pos.screen.width;
					break;
			}
			switch(self.options.edge.y) {
				case 'center':
					edge.y = pos.screen.height / 2;
					break;
				case 'bottom':
					edge.y = pos.screen.height;
					break;
			}
		} else {
			// User passed an edge, so we'll work relative to that window edge
			var edge = {x: pos.win.x, y: pos.win.y};
			switch(self.options.edge.x) {
				case 'center':
					edge.x = (pos.win.width / 2) + pos.win.x;
					break;
				case 'right':
					edge.x = pos.win.width + pos.win.x;
					break;
			}
			switch(self.options.edge.y) {
				case 'center':
					edge.y = (pos.win.height / 2) + pos.win.y;
					break;
				case 'bottom':
					edge.y = pos.win.height + pos.win.y;
					break;
			}
		}
		
		// Calculate the top left coordinate based on reference point and edge point
		fromLeft = edge.x - ref.x;
		fromTop = edge.y - ref.y;
		
		// Set up the options and window name
		var settings = 'width=' + self.options.width + ',height=' + self.options.height + ',left=' + fromLeft + ',top=' + fromTop + (self.options.windowFeatures != '' ? ',' + self.options.windowFeatures : '');
		var name = (this.get('title') != '' ? this.get('title') : this.get('text'));
		
		// Open the window
		if (self.options.reuseWindow && $chk(self.win) && !self.win.closed) {
			self.win.location.href = this.get('href');
		} else {
			self.win = window.open(this.get('href'), name, settings);
		}
		
		// Focus the window, if desired
		if (self.options.focus) {
			self.win.focus();
		}
		
		// Returns the new window object for chaining; never know, might be useful
		return self.win;
	},
	
	// Allows initializing links after the fact, among other things
	addLink: function(el) {
		if ($type(el) == 'string') el = document.id(el);
		el.addEvent('click', this.open);
		el.positionedWindow = this;
	}
});


// This extremely basic class merely collects the dimension info for the current window and screen
var ScreenDimensions = new Class({
	// Standard accessors
	win: {
		width: 0,
		height: 0,
		x: 0,
		y: 0,
		left: 0,
		top: 0
	},
	screen: {
		width: 0,
		height: 0
	},
	
	initialize: function() {
		// Get the dimensions across browsers; IE will unfortunately not include the chrome
		this.screenWidth = screen.availWidth;
		this.screenHeight = screen.availHeight;
		if ($chk(window.screenLeft)) {
			// IE-compatible check for variables
			this.windowX = window.screenLeft;
			this.windowY = window.screenTop
			if (document.documentElement && document.documentElement.clientHeight) {
				this.windowWidth = document.documentElement.clientWidth;
				this.windowHeight = document.documentElement.clientHeight;
			} else if (document.body) {
				this.windowWidth = document.body.clientWidth;
				this.windowHeight = document.body.clientHeight;
			}
		} else {
			// Variables for everyone else
			this.windowX = window.screenX;
			this.windowY = window.screenY;
			this.windowWidth = window.outerWidth;
			this.windowHeight = window.outerHeight;
		}
		
		// Setup standard accessors
		this.win = {
			width: this.windowWidth,
			height: this.windowHeight,
			x: this.windowX,
			y: this.windowY,
			left: this.windowX,
			top: this.windowY
		};
		this.screen = {
			width: this.screenWidth,
			height: this.screenHeight
		};
	}
});