// Inspired by base2 and Prototype
(function(){
	var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

	// The base Class implementation (does nothing)
	this.Class = function(){};

	// Create a new Class that inherits from this class
	Class.extend = function(prop) {
		var _super = this.prototype;

		// Instantiate a base class (but only create the instance,
		// don't run the init constructor)
		initializing = true;
		var prototype = new this();
		initializing = false;

		// Copy the properties over onto the new prototype
		for (var name in prop) {
			// Check if we're overwriting an existing function
			prototype[name] = typeof prop[name] == "function" &&
			typeof _super[name] == "function" && fnTest.test(prop[name]) ?
			(function(name, fn){
				return function() {
					var tmp = this._super;

					// Add a new ._super() method that is the same method
					// but on the super-class
					this._super = _super[name];

					// The method only need to be bound temporarily, so we
					// remove it when we're done executing
					var ret = fn.apply(this, arguments);
					this._super = tmp;

					return ret;
				};
			})(name, prop[name]) :
			prop[name];
		}

		// The dummy class constructor
		function Class() {
			// All construction is actually done in the init method
			if ( !initializing && this.init )
			this.init.apply(this, arguments);
		}

		// Populate our constructed prototype object
		Class.prototype = prototype;

		// Enforce the constructor to be what we expect
		Class.constructor = Class;

		// And make this class extendable
		Class.extend = arguments.callee;

		return Class;
	};
})();

var WildDOM = {
	getById: function(el) {
		if(typeof(el) == 'string') {
			return document.getElementById(el);
		}

		return false;
	},

	getCollectionByClass: function(searchClass, tag, node) {
		var classElements = new Array();
		if ( node == null )
		node = document;
		if ( tag == null )
		tag = '*';
		var els = node.getElementsByTagName(tag);
		var elsLen = els.length;
		var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");

		for (i = 0, j = 0; i < elsLen; i++) {
			if ( pattern.test(els[i].className) ) {
				classElements[j] = els[i];
				j++;
			}
		}

		return classElements;
	},

	getByClass: function(searchClass, tag, node) {
		var collection = this.getCollectionByClass(searchClass, tag, node);

		return collection.length > 0 ? collection[0] : false;
	},

	getCollectionByTag: function(tag, node) {
		if ( node == null )
		node = document;

		var collection = node.getElementsByTagName(tag);

		return collection;
	},

	getByTag: function(tag, node) {
		var collection = this.getCollectionByTag(tag, node);

		return collection.length > 0 ? collection[0] : false;
	},

	createEl: function(type, klass, params) {
		var temp = document.createElement(type);

		if(typeof(klass) != 'undefined' && klass != false) {
			temp.className = klass;
		}

		if(typeof(params) != 'object') {
			params = {};
		}

		for(var i in params) {
			temp.setAttribute(i, params[i]);
		}

		return temp;
	},

	setStyle: function(node, key, value) {
		var rules = [];

		var styles = node.getAttribute('style');

		var stylesSplit = [];

		if(styles != null && typeof(styles) == 'string') {
			stylesSplit = styles.split(';');

			var splitCount = stylesSplit.length;

			for(var i = 0; i < splitCount - 1; i++) {
				rules[i] = stylesSplit[i].replace(/\s+$/, '');
			}
		}

		if(typeof(key) == 'string') {
			rules.push(key + ': ' + value);
		}

		if(typeof(key) == 'object') {
			for(var i in key) {
				rules.push(i + ': ' + key[i]);
			}
		}

		node.setAttribute('style', rules.join(';'));

		return node;
	},

	insertAfter: function(newElement,targetElement) {
		//target is what you want it to go after. Look for this elements parent.
		var parent = targetElement.parentNode;

		//if the parents lastchild is the targetElement...
		if(parent.lastchild == targetElement) {
			//add the newElement after the target element.
			parent.appendChild(newElement);
		} else {
			// else the target has siblings, insert the new element between the target and it's next sibling.
			parent.insertBefore(newElement, targetElement.nextSibling);
		}
	},

	findPrevious: function(o, tag, limit) {
		for(tag = tag.toLowerCase(); o = o.previousSibling;)
		if(o.tagName && o.tagName.toLowerCase() == tag)
		return o;
		else if(limit && o == limit)
			return null;
			return null;
		}
	};

	var Tweetedia = Class.extend({
		scriptFound: false,
		configLoaded: false,
		parentCreated: false,

		feedId: null,

		json: null,

		params: {},

		jsonHooks: {},

		parentHash: null,

		scriptNode: null,
		parentNode: null,

		adHeight: 250,
		adWidth: 300,
		flashHeight: 315,
		flashWidth: 300,

		adParams: {},
		adParamsString: '',

		scriptUrl: null,
		versionUrl: null,
		
		finalSwfUrl: null,
		finalApiUrl: null,

		configMode: false,
		container: null,

		init: function(args) {
			this.configMode = args.configMode || false;
			this.version = args.version || null;
			this.params = args.params || {};
			var containerString = args.container || null;

			if(containerString != null) {
				this.container = WildDOM.getById(containerString);
			}

			this._findScript();

			if(this.scriptFound == true) {
				this._log('Script found, attempting to place parent node');

				this._createNode();

				if(this.parentCreated == true) {
					this._log('Parent node placed, hash: ' + this.parentHash);

					if(args.ident.length >= 9) {
						this.feedId = args.ident.substring(8);
						//this.scriptUrl = 'www.stage.tweetology.com';

						if(this.scriptUrl != null && this.versionUrl != null) {
							this.finalSwfUrl = 'http://' + this.scriptUrl + '/' + this.versionUrl + '/tweetedia-loader.swf';
							this.finalApiUrl = 'http://' + this.scriptUrl + '/' + this.versionUrl + '/config/id/' + this.feedId;

							this._createBase();
						} else {
							this._log('Script or Version url invalid or not specified, aborting');
						}
					} else {
						this._log('Invalid ident, aborting and placing stiff budgie');

						this._buildStiff();
					}
				} else {
					this._log('Parent node not could not be created');
				}
			} else {
				this._log('Script tag not found');
			}

			return this;
		},

		reload: function(useApi) {
			if(this.scriptFound == true && this.parentCreated == true && this.feedId != null) {
				this.parentNode.innerHTML = '';

				this._createNode();

				var tempFinalApi = this.finalApiUrl;

				if(typeof(useApi) == 'undefined' || useApi != 1) {
					var tempScriptUrl = 'www.tweetedia.com';

					if(this.scriptUrl == 'api.dev.tweetedia.com') {
						tempScriptUrl = 'www.dev.tweetedia.com';
					} else if(this.scriptUrl == 'api.stage.tweetedia.com') {
						tempScriptUrl = 'www.stage.tweetedia.com';
					}

					this.finalApiUrl = 'http://' + tempScriptUrl + '/publisher/feed/config';
				} else {
					this.finalApiUrl = this.finalApiUrl + '/cache/1';
				}

				this._createBase();

				this.finalApiUrl = tempFinalApi;

				return this;
			}
		},

		_findScript: function() {
			if(this.configMode == true && this.container != null) {
				this.parentHash = new Date().getTime();

				this.scriptFound = true;

				return true;
			}

			var scripts = document.getElementsByTagName('script');

			for(var i in scripts) {
				var script = scripts[i];

				if(typeof(script) == 'object' && typeof(script.innerHTML) != 'undefined' && script.innerHTML != '' && script.innerHTML.search(/new Tweetedia\(/) != -1 && script.defer == false) {
					script.defer = 'defer';

					this.parentHash = new Date().getTime();

					this.scriptNode = script;

					this.scriptFound = true;

					return true;
				}
			}

			return false;
		},

		_createNode: function() {
			var self = this;

			var div = document.createElement('div');

			div.id = 'twee-widget-' + this.parentHash;
			div.className = 'twee-widget';
			div.style.width = this.flashWidth + 'px';

			if(this.configMode == true && this.container != null) {
				this.container.appendChild(div);
			} else {
				WildDOM.insertAfter(div, this.scriptNode);
			}

			var widgets = WildDOM.getCollectionByClass('twee-widget', 'div');

			for(var i in widgets) {
				widget = widgets[i];

				if(widget.id == 'twee-widget-' + this.parentHash) {
					this.parentNode = widget;

					this.parentCreated = true;

					if(this.configMode == true && this.container != null) {
						var currentDomain = document.domain;

						if(this.version != null) {
							this.versionUrl = this.version;

							this.scriptUrl = 'api.tweetology.com';

							if(currentDomain == 'www.dev.tweetedia.com') {
								this.scriptUrl = 'api.dev.tweetedia.com';
							} else if(currentDomain == 'www.stage.tweetedia.com') {
								this.scriptUrl = 'api.stage.tweetedia.com';
							} else if(currentDomain == 'www.stage.tweetedia.com') {
								this.scriptUrl = 'api.dev.tweetology.com';
							} else if(currentDomain == 'www.stage.tweetedia.com') {
								this.scriptUrl = 'api.stage.tweetology.com';
							}

						}
					} else {
						var s = WildDOM.findPrevious(this.scriptNode, 'script', 5);

						if(s != null) {
							var scriptSrc = s.src;

							scriptUrl = scriptSrc.replace('http://', '');

							scriptSrcSplit = scriptUrl.split('/');

							this.scriptUrl = scriptSrcSplit[0].replace('tweetedia','tweetology');
							this.versionUrl = scriptSrcSplit[1];
						}
					}

					return true;
				}
			}

			return false;
		},

		_createBase: function() {
			var self = this;
			
			var html = '<div class="twee-flash" style="height: ' + this.flashHeight + 'px;">\
			<object width="' + this.flashWidth + '" height="' + this.flashHeight + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="Tweetedia" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">\
			<param name="movie" value="' + this.finalSwfUrl + '">\
			<param name="quality" value="high">\
			<param name="bgcolor" value="#869ca7">\
			<param name="wmode" value="transparent">\
			<param name="allowScriptAccess" value="always">\
			<param name="flashvars" value="config=' + this.finalApiUrl + '&instance=' + this.parentHash + '">\
			<embed width="' + this.flashWidth + '" height="' + this.flashHeight + '" align="middle" wmode="transparent" flashvars="config=' + this.finalApiUrl + '&instance=' + this.parentHash + '" src="' + this.finalSwfUrl + '" bgcolor="#ffffff" name="Tweetedia" play="true" loop="false" quality="high" allowscriptaccess="always" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer">\
			</object>\
			</div>\
			<div class="twee-ad" style="overflow: hidden; height: ' + this.adHeight + 'px;">\
			</div>\
			<div class="twee-footer" style="display: none; height: 35px;">\
			<div class="twee-footer-rounded" style="background-position: top center; background-color: #000; background-image: url(http://www.tweetedia.com/images/widget/footer_30.png); background-repeat: no-repeat; height: 30px; text-align: center;">\
			<div class="twee-footer-rounded-pb" style="padding-top: 10px;">\
			<a class="twee-footer-rounded-pb-a" href="http://www.tweetedia.com" style="padding: 1px 6px; background-color: #555; -moz-border-radius: 8px; -webkit-border-radius: 8px;" target="_blank"><img style="position: relative; top: 2px; border: 0;" src="http://www.tweetedia.com/images/widget/pb_light.png"></a>\
			</div>\
			</div>\
			<div class="twee-footer-rounded" style="background-color: #000; overflow: hidden; height: 2px; margin: 0 1px;"></div>\
			<div class="twee-footer-rounded" style="background-color: #000; overflow: hidden; height: 1px; margin: 0 2px;"></div>\
			<div class="twee-footer-rounded" style="background-color: #000; overflow: hidden; height: 1px; margin: 0 3px;"></div>\
			<div class="twee-footer-rounded" style="background-color: #000; overflow: hidden; height: 1px; margin: 0 5px;"></div>\
			</div>';
			
			this.parentNode.innerHTML = html;

			Tweetedia['parseConfig_' + this.parentHash] = function(data) {
				self.json = data;

				self._postConfig();
			}
		},

		_buildStiff: function() {
			this.parentNode.appendChild(WildDOM.createEl('img', false, {
				align: 'center',
				src: 'stiff-budgie.jpg',
				style: 'background-color: white; padding: 15px;'
			}));
		},

		_postConfig: function() {
			var adSize = this.json.ad.sz.split('x');

			this.adHeight = adSize[1];
			this.adWidth = adSize[0];

			var jsonHeight = this.json.height;

			//jsonHeight -= 35;
			//jsonHeight -= this.adHeight;

			this.flashHeight = jsonHeight;
			this.flashWidth = this.json.width;

			this._buildAd();

			this._applyJsonStyles();
		},

		_buildAd: function() {
			var adZone = this.json.ad.zone;

			if(this.json.ad.site == 'noshow') {
				WildDOM.getByClass('twee-ad', 'div', this.parentNode).style.display = 'none';
				return;
			}

			WildDOM.getByClass('twee-ad', 'div', this.parentNode).style.height = this.adHeight + 'px';

			if(typeof(this.json.ad.params) == 'object') {
				for(var i in this.json.ad.params) {
					this.adParams[i] = this.json.ad.params[i];
				}
			}

			for(var i in this.params) {
				this.adParams[i] = this.params[i];
			}

			for(var i in this.adParams) {
				this.adParamsString = this.adParamsString + i + '=' + this.adParams[i] + ';';
			}

			if(this.configMode == true) {
				adZone = 'test';
			}

			var template = '<iframe src="http://ad.doubleclick.net/adi/' + this.json.ad.site + '/' + adZone + ';sz=' + this.json.ad.sz + ';' + this.adParamsString + 'ord=[timestamp]?" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" height="' + this.adHeight + '" width="' + this.adWidth + '"><script type="text/javascript" src="http://ad.doubleclick.net/adj/' + this.json.ad.site + '/' + adZone + ';sz=' + this.json.ad.sz + ';' + this.adParamsString + 'abr=!ie;ord=[timestamp]?"></script>\
			</iframe>\
			<noscript>\
			<a href="http://ad.doubleclick.net/jump/' + this.json.ad.site + '/' + adZone + ';sz=' + this.json.ad.sz + ';' + this.adParamsString + 'ord=[timestamp]?">\
			<img src="http://ad.doubleclick.net/ad/' + this.json.ad.site + '/' + adZone + ';sz=' + this.json.ad.sz + ';' + this.adParamsString + 'ord=[timestamp]?" border="0" alt="" />\
			</a>\
			</noscript>';

			WildDOM.getByClass('twee-ad', 'div', this.parentNode).innerHTML = template;
		},

		_applyJsonStyles: function() {
			this.parentNode.style.width = this.flashWidth + 'px';

			WildDOM.getByClass('twee-flash', 'div', this.parentNode).style.height = this.flashHeight + 'px';

			var objectNode = WildDOM.getByTag('object', this.parentNode);

			if(objectNode != false) {
				objectNode.setAttribute('height', this.flashHeight);
				objectNode.setAttribute('width', this.flashWidth);
			}

			var embedNode = WildDOM.getByTag('embed', this.parentNode);

			if(embedNode != false) {
				embedNode.setAttribute('width', this.flashWidth);
				embedNode.setAttribute('height', this.flashHeight);
			}

			var footerDivs = WildDOM.getCollectionByClass('twee-footer-rounded', 'div', WildDOM.getByClass('twee-footer'));

			for(var i in footerDivs) {
				footerDiv = footerDivs[i];

				footerDiv.style.backgroundColor = this.json.skin.background.replace('0x', '#');
			}

			var pbA = WildDOM.getByClass('twee-footer-rounded-pb-a', 'a', WildDOM.getByClass('twee-footer'));

			pbA.href = this.json.skin.poweredByTarget;

			pbA.style.backgroundColor = this.json.skin.poweredByBackground.replace('0x', '#');
			pbA.style.border = '1px solid ' + this.json.skin.poweredByBorder.replace('0x', '#');

			if(this.json.skin.style != 'shiny') {
				WildDOM.getByClass('twee-footer-rounded', 'div', this.parentNode).style.backgroundImage = '';

				WildDOM.getByClass('twee-footer-rounded-pb', 'div', this.parentNode).style.paddingTop = '8px';
			}

			WildDOM.getByClass('twee-footer', 'div', this.parentNode).style.display = 'block';
		},

		_isIE: function() {
			return (((navigator.appVersion.indexOf("MSie") != -1) || navigator.appVersion.indexOf("MSIE") != -1) && !window.opera) ? true : false;
		},

		_log: function(message) {
			if(typeof(console) == 'object' && typeof(console.log) == 'function') {
				console.log(message);
			} else {
				// Do nothing
			}
		}
	});

	var tweetediaConfigSetup = function(data, instance) {
		var fnName = 'Tweetedia.parseConfig_' + instance + '(' + data + ')';

		var fn = new Function(fnName);

		fn();

		return false;
	};
