// $Id: common.js 3 2008-08-06 04:26:59Z steven $
/*
 * Anfiniti RPG System
 * Author: Steven Harris/Indigo
 * 
 * This system has no real license yet. For now, feel free to browse the code,
 * just don't use it on your own server without permission from the author.
 */

var rpg = {};

rpg.js_link = function(lnk) {
	return RPGPATH + '/' + lnk + '/';
}
rpg.url = rpg.js_link;

rpg.stopEvents = function() { new Event().stop(); return false; };

/**
 * Basic implementation of a popup div
 */
rpg.Popup = new Class({

	initialize: function(xp, yp, w, t, c, objName)
	{
		// create the element and put it inside the body
		this.element = new Element('div', {
			'styles': {
				'position'  : 'absolute',
				'zIndex'    : 50,
				'left'      : xp,
				'top'       : yp,
				'width'     : w,
				'opacity'   : 0
			}
		});
		this.element.injectInside(document.body);
		
		// initialize content to blank
		this.title   = t;
		this.content = c;
		this.draggable = false;
		this.objName   = objName;
		this.dirty = true;
	},

	update: function(xpos, ypos, wdth, titl, content)
	{
		this.element.setStyles({
			'left' : xpos,
			'top'  : ypos,
			'width': wdth
		});
		this.title   = titl;
		this.content = content;
		this.dirty = true;
	},

	paint: function()
	{
		if (this.dirty) {
			this.element.setHTML(
			'<table class="tborder" cellpadding="6" cellspacing="1" border="0" width="100%" align="center">' +
			'<tr><td class="thead" id="popup-title">' + this.title + '</td><td align="right" class="thead" width="1%"><a href="#" onclick="' + this.objName + '.hide(); return false;">[Close]</a></td></tr>' +
			'<tr><td class="alt1" colspan="2">' + this.content +
			'</td></tr>' +
			'</table>'
			);
			this.dirty = false;
		}
		
// 		if (!this.draggable) {
// 			//this.element.makeDraggable({'handle': this.draghandle});
// 			this.element.makeDraggable();
// 			this.draggable = true;
// 		}
		
		this.show();
	},

	show: function()
	{
		// already showing? always make it show so it can refresh.
		// possibly fix later so it doesn't run the effect again
 		if (this.showing()) {
 			return;
 		}
		
		var info = this.element.getCoordinates(); // width height left top right bottom
	
		// init effects
		var showfx = this.element.effects({duration: 200, transition: Fx.Transitions.Quart.easeOut});
		showfx.start({
			'top'    : [info.top + 20, info.top],
			'opacity': [0, 0.95]
		});
	},

	hide: function()
	{
		// not showing?
		if (this.element.getStyle('opacity') == 0) {
		//	return false;
		}
		
		var info = this.element.getCoordinates(); // width height left top right bottom
		
		// init effects
		var showfx = this.element.effects({duration: 200, transition: Fx.Transitions.Quart.easeOut});
		showfx.start({
			'top'    : [info.top, info.top + 20],
			'opacity': [0.95, 0]
		});
		
		return false;
	},
	
	toggle: function()
	{
		if (!this.showing()) {
			this.paint();
		}
		else {
			this.hide();
		}
	},

	display: function(xpos, ypos, wdth, titl, content)
	{
		this.update(xpos, ypos, wdth, titl, content);
		this.paint();
	},

	updatePortion: function(json)
	{
		for (var k in json) {
			if (k == 'left' || k == 'top' || k == 'width') {
				this.element.setStyle(k, json[k]);
			}
		}
	
		if (json.title) {
			this.title = json.title;
		}
		if (json.content) {
			this.content = json.content;
		}
		
		this.dirty = true;
	},
	
	showing: function()
	{
		return this.element.getStyle('opacity') > 0.01;
	}
	
});

// hack for IE... for some reason this breaks the party page
//if (PATHINFO[0] != 'party') {
	window.addEvent('domready', function() {
		rpg.popup = new rpg.Popup(0, 0, 300, "", "", 'rpg.popup');
	});
//}

/**
 * Simple cache manager.
 */
rpg.Cache = new Class({
	
	initialize: function(disposeRate)
	{
		this.cacheData   = {};
		this.expirations = {};
		// garbage collect each minute by default
		this.dispose.periodical($pick(disposeRate, 60 * 1000), this);
	},
	
	set: function(key, val, expiry)
	{
		this.cacheData[key]   = val;
		this.expirations[key] = [$time() / 1000, expiry || 180];
	},
	
	get: function(key)
	{
		if (!this.cacheData[key]) {
			return null;
		}
		
		// check age
		if (this.expired(key)) {
			return null;
		}
		else {
			return this.cacheData[key];
		}
	},
	
	expired: function(key)
	{
		return ($time() / 1000 > this.expirations[key][0] + this.expirations[key][1]);
	},
	
	// disposes all cache entries that have expired
	dispose: function()
	{
		for (var key in this.cacheData) {
			if (this.expired(key)) {
				delete this.cacheData[key];
				delete this.expirations[key];
			}
		}
	}
	
});
rpg.cache = new rpg.Cache;

/**
 * Makes AJAX requests that use an internal cache, to speed up execution and
 * help reduce the number of hits to the server.
 */
rpg.CachedAjax = Ajax.extend({

	options: {
		expiry: 120,
		forceUpdate: false
	},
	
	initialize: function(url, options)
	{
		this.parent(url, options);
		this.cachedQuery = '';
	},

	onComplete: function()
	{
		// set the cache entry to the response
		if (this.cachedQuery != '') {
			rpg.cache.set(this.cachedQuery, this.response.text, this.options.expiry);
		}
		this.parent();
	},

	request: function(data)
	{
		data = data || this.options.data;
		switch($type(data)){
			case 'element': data = $(data).toQueryString(); break;
			case 'object': data = Object.toQueryString(data);
		}
		if (this._method) data = (data) ? [this._method, data].join('&') : this._method;
		
		// before doing a remote call, check for query's existence in cache
		this.cachedQuery = 'ca_' + this.url + '?' + data;
		var cacheEntry = rpg.cache.get(this.cachedQuery);
		if (!this.options.forceUpdate && cacheEntry) {
			// we're done before we started, populate response and fire success event
			// empty this.cachedQuery first so it doesn't get re-cached
			this.cachedQuery = '';
			this.response = {'text': cacheEntry, 'xml': null};
			this.fireEvent('onSuccess', [this.response.text, this.response.xml]);
			this.callChain();
			return this;
		}
		
		// aw, no cache, we need to hit the server
		return this.send(this.url, data);
	}

});

rpg.fetchOffset = function(elemId)
{
	var pos = $(elemId).getPosition();
	return { 'left': pos.x, 'top': pos.y };
};

rpg.createHiddenFields = function(obj)
{
	var str = '';
	for (var key in obj) {
		str += '<input type="hidden" name="' + key + '" value="' + obj[key] + '" />\n';
	}
	return str;
};

// we do it this way so that users can't click "copy link address" and
// end up giving away their security token
rpg.applyTokens = function()
{
	var anchors = $$(document.getElementsByTagName('a')).filter(function(el) {
		return (el.className && el.className.contains('has-token', ' '));
	});
	
	anchors.each(function(el) {
		el.addEvent('click', function(event) {
			new Event(event).stop();
			var href = el.getProperty('href');
			href += href.contains('?') ? '&' : '?';
			href += 'token=' + VERIFYTOKEN;
			window.location.href = href;
		});
	});
};
window.addEvent('domready', rpg.applyTokens);

// not really a shortcut anymore.
rpg.selidx = function(obj)
{
	//return obj.options[obj.selectedIndex].value;
	return $(obj).getValue();
};

rpg.setAurum = function(amount, add)
{
	var el = $('aurum-header');
	if (add) {
		amount += el.getProperty('name').substr(4).toInt();
	}
	
	el.setHTML(rpg.formatNumber(amount));
};

rpg.formatNumber = function(num)
{
	num = '' + num;
	var len = num.length;
	
	if (len < 4) {
		return num;
	}
	
	var fmt = '';
	var i;
	for (i = len - 4; i >= 0; i -= 3) {
		fmt = ',' + num.substr(i + 1, 3) + fmt;
	}
	
	if (i < 0) {
		fmt = num.substr(0, 4 + i) + fmt;
	}
	
	return fmt;
};

rpg.resizeTextarea = function(el, bigsmall)
{
	if (bigsmall) {
		var rows = 4;
		var cols = 8;
	}
	else {
		var rows = -4;
		var cols = -8;
	}
	
	var el = $(el);
	if (!$defined(el.orig_rows)) {
		el.orig_rows = el.rows;
		el.orig_cols = el.cols;
	}

	var newrows = el.rows + rows;
	var newcols = el.cols + cols;
	
	// don't let it get smaller than the original
	if (newrows >= el.orig_rows && newcols >= el.orig_cols) {
		el.rows = newrows;
		el.cols = newcols;
	}

	return false;
};

rpg.fadeIn = function(el)
{
	el = $(el);
	if (el.getStyle('display') != 'none') {
		return false;
	}
	
	el.setStyles({display: '', opacity: 0});
	var fx = el.effect('opacity', {duration: 500, transition: Fx.Transitions.Quart.easeOut});
	fx.start(0, 1);
	
	return false;
};

rpg.fadeOut = function(el)
{
	el = $(el);
	if (el.getStyle('display') == 'none') {
		return false;
	}
	
	var fx = el.effect('opacity', {duration: 500, transition: Fx.Transitions.Quart.easeOut});
	fx.addEvent('onComplete', function() { el.setStyles({display: 'none', opacity: 1}); });
	fx.start(1, 0);
	
	return false;
};	

rpg.startLoadAnim = function()
{
	try {
		$('refreshtarget').innerHTML = '<img src="/forum/images/misc/progress.gif" width="16" height="16" />';
	}
	catch (ex) {}
	$(document.body).setStyle('cursor', 'wait');
};

rpg.stopLoadAnim = function()
{
	try {
		$('refreshtarget').innerHTML = '&nbsp;';
	}
	catch (ex) {}
	$(document.body).setStyle('cursor', 'default');
};

rpg.ajaxError = function(rtext)
{
	if (rtext.substr(0, 5) == 'FALSE') {
		if (rtext.length > 5) {
			alert(rtext.substr(5));
		}
		else {
			alert('An error has occurred.');
		}
		return true;
	}
	return false;
};

rpg.ajaxErrorDecorator = function(func)
{
	return function(rtext, rxml) {
		if (rpg.ajaxError(rtext)) {
			return;
		}
		func(rtext, rxml);
	};
};
