/**
 ** Renders a customized guild tabard using the HTML5 <canvas> element.
 **
 ** @copyright   2010, Blizzard Entertainment, Inc
 ** @class       GuildTabard
 ** @requires    
 ** @example
 **
 **      var tabard = new GuildTabard('canvas-element', {
 **	 		'ring': 'alliance',
 **			'bg': [ 0, 2 ],
 **			'border': [ 0, 5 ],
 **			'emblem': [ 65, 12 ]
 **		});
 **
 **/

function GuildTabard(canvas, tabard) {
	var self = this,
		canvas = document.getElementById(canvas),
		context = null,
		_path = '/images/games/wow/guild/tabards/',
		_width = canvas.width,
		_height = canvas.height,
		_src = [],
		_img = [],
		_colorMap = [],
		_color = [],
		_position = [];

	self.initialize = function() {
		if (canvas === null || !document.createElement('canvas').getContext || !_isInteger(tabard.bg[0]) || !_isInteger(tabard.border[0]) || !_isInteger(tabard.emblem[0]))
			return false;

		_src = [
			_path + 'ring-' + tabard.ring + '.png',
			_path + 'shadow_' + Core.zeroFill(tabard.bg[0], 2) + '.png',
			_path + 'bg_' + Core.zeroFill(tabard.bg[0], 2) + '.png',
			_path + 'overlay_' + Core.zeroFill(tabard.bg[0], 2) + '.png',
			_path + 'border_' + Core.zeroFill(tabard.border[0], 2) + '.png',
			_path + 'emblem_' + Core.zeroFill(tabard.emblem[0], 2) + '.png',
			_path + 'hooks.png'
		];
		_colorMap = [
			null,
			null,
			[[215,32,112],[171,0,76],[87,0,0],[225,105,26],[180,56,0],[133,11,0],[237,151,22],[205,110,0],[155,61,0],[239,207,20],[207,162,0],[158,113,0],[226,216,20],[183,177,0],[133,128,0],[206,209,24],[159,161,3],[112,115,0],[153,206,27],[108,154,3],[65,108,0],[30,210,96],[4,157,63],[0,110,11],[29,206,169],[4,152,122],[0,107,74],[33,177,214],[3,109,139],[0,81,111],[72,125,193],[38,85,145],[0,39,98],[188,75,195],[145,42,155],[108,8,128],[202,17,191],[173,0,162],[124,0,116],[219,30,160],[149,0,97],[121,0,68],[160,108,44],[108,66,15],[53,16,0],[15,26,31],[117,124,120],[136,145,139],[156,166,159],[211,211,198],[229,107,140]],
			null,
			[[97,42,44],[109,69,46],[119,101,36],[118,114,36],[108,118,36],[85,108,48],[76,109,48],[48,108,66],[48,105,107],[48,80,108],[55,60,100],[87,54,100],[100,55,76],[103,51,53],[153,159,149],[38,46,38],[155,94,28]],
			[[102,0,32],[103,35,0],[103,69,0],[103,86,0],[98,102,0],[80,102,0],[54,102,0],[0,102,30],[0,102,86],[0,72,102],[9,42,94],[86,9,94],[93,10,79],[84,54,10],[177,183,176],[16,20,22],[221,163,90]]
		];
		_color = [
			null,
			null,
			[ _colorMap[2][tabard.bg[1]][0], _colorMap[2][tabard.bg[1]][1], _colorMap[2][tabard.bg[1]][2] ],
			null,
			[ _colorMap[4][tabard.border[1]][0], _colorMap[4][tabard.border[1]][1], _colorMap[4][tabard.border[1]][2] ],
			[ _colorMap[5][tabard.emblem[1]][0], _colorMap[5][tabard.emblem[1]][1], _colorMap[5][tabard.emblem[1]][2] ],
			null
		];
		_position = [
			[ 0, 0, (_width*216/240), (_width*216/240) ],
			[ (_width*18/240), (_width*27/240), (_width*179/240), (_width*216/240) ],
			[ (_width*18/240), (_width*27/240), (_width*179/240), (_width*210/240) ],
			[ (_width*18/240), (_width*27/240), (_width*179/240), (_width*210/240) ],
			[ (_width*31/240), (_width*40/240), (_width*147/240), (_width*159/240) ],
			[ (_width*33/240), (_width*57/240), (_width*125/240), (_width*125/240) ],
			[ (_width*18/240), (_width*27/240), (_width*179/240), (_width*32/240) ]
		];
		_img = [ new Image(), new Image(), new Image(), new Image(), new Image(), new Image(), new Image() ];

		$(canvas).hide();

		context = canvas.getContext('2d');

		_loadImage(0);
	}

	function _loadImage(count) {
		if (count >= _src.length) {
			_render(0);
			return;
		}
		$.ajax({
			'url': _src[count],
			'beforeSend': function() {
				_loadImage(count + 1);
			}
		});
	}

	function _render(index) {
		var _oldCanvas = new Image(),
			_newCanvas = new Image();

		_img[index].src = _src[index];

		_img[index].onload = function() {
			_oldCanvas.src = canvas.toDataURL('image/png');
		}

		_oldCanvas.onload = function() {
			canvas.width = 1;
			canvas.width = _width;
			context.drawImage(_img[index], _position[index][0], _position[index][1], _position[index][2], _position[index][3]);

			if (_color[index] !== null) {
				_colorize(_color[index][0], _color[index][1], _color[index][2]);
			}

			_newCanvas.src = canvas.toDataURL('image/png');
			context.drawImage(_oldCanvas, 0, 0, _width, _height);
		}

		_newCanvas.onload = function() {
			context.drawImage(_newCanvas, 0, 0, _width, _height);
			index++;
			if (index < _src.length) {
				_render(index);
			} else {
				$(canvas).fadeIn(100);
			}
		}
	}

	function _colorize(r, g, b) {
		var imageData = context.getImageData(0, 0, _width, _height),
			pixelData = imageData.data,
			i = pixelData.length,
			intensityScale = 19,
			blend = 1 / 3,
			added_r = r / intensityScale + r * blend,
			added_g = g / intensityScale + g * blend,
			added_b = b / intensityScale + b * blend,
			scale_r = r / 255 + blend,
			scale_g = g / 255 + blend,
			scale_b = b / 255 + blend;

		imageData = context.getImageData(0, 0, _width, _height);
		pixelData = imageData.data;
		i = pixelData.length;
		do {
			if (pixelData[i + 3] !== 0) {
				pixelData[i] = pixelData[i] * scale_r + added_r;
				pixelData[i + 1] = pixelData[i + 1] * scale_g + added_g;
				pixelData[i + 2] = pixelData[i + 2] * scale_b + added_b;
			}
		} while (i -= 4);
		context.putImageData(imageData, 0, 0);
	}

	function _isInteger(n) {
		if (!isNaN(parseFloat(n)) && isFinite(n)) {
			return n % 1 === 0;
		} else {
			return false;
		}
	}

	this.initialize();
}


$(function() {
	Wow.bindItemTooltips();
	Wow.bindCharacterTooltips();
//	Fansite.initialize();
});

var Wow = {

	/**
	 * Display or hide the video.
	 */
	toggleInterceptVideo: function() {
		$("#video, #blackout, #play-trailer").toggle();
		return false;
	},

	/**
	 * Bind item tooltips to links.
	 * Gathers the item ID from the href, and the optional params from the data-item attribute.
	 */
	bindItemTooltips: function() {
		var doc = $(document);
		var callback = function() {
			if (this.href == 'javascript:;' || this.href.indexOf('#') == 0 || this.rel == 'np')
				return;
			var self = $(this),
				data = self.data('item'),
				href = self.attr('href').replace(Core.baseUrl +'/item/', ""),
				id = parseInt(href),
				query = (data) ? '?'+ data : "";

			if (id && id > 0)
				Tooltip.show(this, '/item/'+ id +'/tooltip'+ query, true);
			
		};

		doc.undelegate('a[href*="/item/"]', 'mouseover.tooltip', callback);
		doc.delegate('a[href*="/item/"]', 'mouseover.tooltip', callback);
	},

	/**
	 * Bind character tooltips to links.
	 * Add rel="np" to disable character tooltips on links.
	 */
	bindCharacterTooltips: function() {
		var doc = $(document);
		var callback = function() {
			if (this.href == 'javascript:;' || this.href.indexOf('#') == 0 || this.rel == 'np' || this.href.indexOf('/vault/') != -1)
				return;

			var self = $(this),
				href = self.attr('href').replace(Core.baseUrl +'/character/', "").split('/');

			if (location.href.toLowerCase().indexOf('/'+ href[1] +'/') != -1 && this.rel != 'allow')
				return;

			Tooltip.show(this, '/character/'+ encodeURIComponent(href[0]) +'/'+ href[1] +'/tooltip', true);
		};

		doc.undelegate('a[href*="/character/"]', 'mouseover.tooltip', callback);
		doc.delegate('a[href*="/character/"]', 'mouseover.tooltip', callback);
	},

	/**
	 * Update the events within the sidebar.
	 *
	 * @param id
	 * @param status
	 */
	updateEvent: function(id, status) {
		$('#event-'+ id +' .actions').fadeOut('fast');

		$.ajax({
			url: $('.profile-link').attr('href') +'event/'+ status,
			data: { eventId: id },
			dataType: "json",
			success: function(data) {
				$('#event-'+ id).fadeOut('fast', function() {
					$(this).remove();
				});
			}
		});

		return false;
	},

	/**
	 * Load the browse.json data and display the dropdown menu.
	 *
	 * @param node
	 * @param url
	 */
	browseArmory: function(node, url) {
		if ($('#menu-tier-browse').is(':visible'))
			return;

		Menu.load('browse', url);
		Menu.show(node, '/', { set: 'browse' });
	},

	/**
	 * Creates the html nodes for basic tooltips.
	 *
	 * @param title
	 * @param description
	 * @param icon
	 */
	createSimpleTooltip: function(title, description, icon) {
		var $tooltip = $('<ul/>');

		if (icon)
			$('<li/>').append(Wow.Icon.framedIcon(icon, 56)).appendTo($tooltip);

		if (title)
			$('<li/>').append($('<h3/>').text(title)).appendTo($tooltip);

		if (description)
			$('<li/>').addClass('color-tooltip-yellow').html(description).appendTo($tooltip);

		return $tooltip;
	},

	/**
	 * Add new BML commands to the editor.
	 */
	addBmlCommands: function() {
		BML.addCommands([
			{
				type: 'item',
				tag: 'item',
				filter: true,
				selfClose: true,
				prompt: Msg.bml.itemPrompt,
				pattern: [
					'\\[item="([0-9]{1,5})"\\s*/\\]'
				],
				result: [
					'<a href="'+ Core.baseUrl +'/item/$1">'+ Core.host + Core.baseUrl +'/item/$1</a>'
				]
			}
		]);
	}

};

Wow.Icon = {

	/**
	 * CDN for images.
	 */
	cdn: 'http://us.battle.net/wow-assets/static/images',

	/**
	 * Generate icon path.
	 *
	 * @param name
	 * @param size
	 */
	getUrl: function(name, size) {
		return Wow.Icon.cdn +'/icons/'+ size +'/'+ name +'.jpg';
	},

	/**
	 * Create frame icon markup.
	 *
	 * @param name
	 * @param size
	 */
	framedIcon: function(name, size) {
		var iconSize = 56;

		if (size <= 18)
			iconSize = 18;
		else if (size <= 36)
			iconSize = 36;

		var $icon = $('<span/>').addClass('icon-frame frame-' + size);

		if (size == 18 || size == 36 || size == 56) {
			$icon.css('background-image', 'url(' + Wow.Icon.getUrl(name, iconSize) + ')');
		} else {
			$icon.append($('<img/>').attr({
				width: size,
				height: size,
				src: Wow.Icon.getUrl(name, iconSize)
			}));
		}

		return $icon;
	}

}

/**
 * 3rd-party fansite integration.
 */
var Fansite = {

	/**
	 * DOM object for menu.
	 */
	object: null,

	/**
	 * Current hovered node.
	 */
	node: null,

	/**
	 * Closing timer.
	 */
	timer: null,

	/**
	 * Map of sites and available URLs.
	 */
	sites: {
		wowhead: {
			name: 'Wowhead',
			site: 'http://www.wowhead.com/',
			locales: ['de', 'es', 'fr', 'ru'],
			urls: {
				achievement: ['achievements', 'achievement={0}'],
				character: ['profiles', function(params) {
					return 'profile='+ encodeURIComponent(params[1]) + '.' + encodeURIComponent(params[3]) + '.' + encodeURIComponent(params[2].toLowerCase());
				}],
				faction: ['factions', 'faction={0}'],
				'class': ['classes', 'class={0}'],
				object: ['objects', 'object={0}'],
				talentcalc: ['talent', function(params) {
					return 'talent#' + params[1].replace('-', '') + '-' + params[2];
				}],
				skill: ['skills', 'skill={0}'],
				race: ['races', 'race={0}'],
				quest: ['quests', 'quest={0}'],
				spell: ['spells', 'spell={0}'],
				event: ['events', 'event={0}'],
				title: ['titles', 'title={0}'],
				zone: ['zones', 'zone={0}'],
				item: ['items', 'item={0}'],
				npc: ['npcs', 'npc={0}'],
				pet: ['pets', 'pet={0}']
			}
		},
		wowpedia: {
			name: 'Wowpedia',
			site: 'http://www.wowpedia.org/',
			locales: [],
			urls: {
				faction: ['Factions', '{1}'],
				'class': ['Classes', '{1}'],
				skill: ['Profession', '{1}'],
				race: ['Races', '{1}'],
				zone: ['Zones', '{1}'],
				pet: ['Pets', '{1}']
			},
			buildUrl: function(params) {
				return encodeURIComponent(params[2].replace(/\s+/g, '_'));
			}
		}
	},

	/**
	 * Map of content types and available sites for that type.
	 */
	map: {
		achievement: ['wowhead'],
		character: ['wowhead'],
		faction: ['wowhead', 'wowpedia'],
		'class': ['wowhead', 'wowpedia'],
		object: ['wowhead'],
		talentcalc: ['wowhead'],
		skill: ['wowhead', 'wowpedia'],
		quest: ['wowhead'],
		spell: ['wowhead'],
		event: ['wowhead'],
		title: ['wowhead'],
		arena: [],
		guild: [],
		zone: ['wowhead', 'wowpedia'],
		item: ['wowhead', 'wowpedia'],
		race: ['wowhead', 'wowpedia'],
		npc: ['wowhead', 'wowpedia'],
		pet: ['wowhead', 'wowpedia'],
		pvp: []
	},

	/**
	 * Create the menu HTML and delegate link events.
	 *
	 * @constructor
	 */
	initialize: function() {
		Fansite.object = $('<div/>')
			.attr('id', 'fansite-menu')
			.addClass('ui-fansite')
			.appendTo('body')
			.mouseleave(Fansite.hide)
			.mouseenter(function() {
				window.clearTimeout(Fansite.timer);
				Fansite.timer = null;
			});

		var doc = $(document);
		var callback = function() {
			var node = $(this),
				params = Fansite.read(node.data('fansite'));

			Fansite.find(node, params);
			return false;
		};

		doc.undelegate('a[data-fansite]', 'mouseover.fansite', callback);
		doc.delegate('a[data-fansite]', 'mouseover.fansite', callback);
	},

	/**
	 * Split params the awesome way!
	 *
	 * @param data
	 * @return array
	 */
	read: function(data) {
		return data.split('|');
	},

	/**
	 * Generate links from params.
	 *
	 * @param params
	 * @return array
	 */
	createLinks: function(params) {
		var type = params[0],
			map = Fansite.map[type],
			links = [];

		if (map.length > 0) {
			var site, url, urls;

			for (var i = 0, len = map.length; i < len; ++i) {
				site = Fansite.sites[map[i]];
				url = Fansite.createUrl(site),
				urls = site.urls[type];

				if (params.length <= 1) {
					url += urls[0];
				} else {
					if (typeof site.buildUrl == 'function') {
						url += site.buildUrl(params);
					} else {
						var urlPattern = urls[1];
						
						if (typeof urlPattern == 'function') {
							url += urlPattern(params);
						} else {
							for (var j = 1; j < params.length; ++j) {
								urlPattern = urlPattern.replace('{' + (j - 1) + '}', encodeURIComponent(params[j]));
							}
							url += urlPattern;
						}
					}
				}

				links.push('<a href="'+ url +'" target="_blank">'+ site.name +'</a>');
			}
		}

		return links;
	},

	/**
	 * Create the URL based on locale.
	 *
	 * @param site
	 * @return string
	 */
	createUrl: function(site) {
		var url = site.site,
			lang = Core.getLanguage();

		if ($.inArray(lang, site.locales) >= 0)
			url = url.replace('www', lang);

		return url;
	},

	/**
	 * Open up the menu and show the available sites for that type.
	 *
	 * @param node
	 * @param params
	 */
	find: function(node, params) {
		window.clearTimeout(Fansite.timer);

		// Set node
		if (Fansite.node)
			Fansite.node.parent().removeClass('fansite-hover');

		node.parent().addClass('fansite-hover');
		node.mouseleave(function() {
			window.clearTimeout(Fansite.timer);
			Fansite.timer = window.setTimeout(Fansite.hide, 750);
		});

		Fansite.node = node;

		var list = $('<ul/>');
		var links = Fansite.createLinks(params);

		if (links.length == 0) {
			$('<li/>')
				.addClass('first-child')
				.html(Msg.ui.fansiteNone)
				.appendTo(list);

		} else {
			var title = Msg.ui.fansiteFind;

			if (Msg.fansite[params[0]])
				title = Msg.ui.fansiteFindType.replace('{0}', Msg.fansite[params[0]]);

			$('<li/>')
				.addClass('first-child')
				.html(title)
				.appendTo(list);

			for (var i = 0, length = links.length; i < length; ++i) {
				$('<li/>').append(links[i]).appendTo(list);
			}

			// Linkify the button itself if there's only 1 fansite
			if (links.length == 1) {
				node.attr('href', $(links[0]).attr('href'));
				node.attr('target', '_blank');
			}
		}

		Fansite.object.html(list);
		Fansite.position(node);
	},

	/**
	 * Hide the menu.
	 */
	hide: function() {
		Fansite.object.fadeOut('fast');

		if (Fansite.node) {
			Fansite.node.parent().removeClass('fansite-hover');
			Fansite.node = null;
		}
	},

	/**
	 * Position the menu at the middle right.
	 *
	 * @param node
	 */
	position: function(node) {
		var offset = node.offset(),
			nodeWidth = node.outerWidth(),
			nodeHeight = node.outerHeight(),
			winWidth = ($(window).width() / 3),
			width = Fansite.object.outerWidth(),
			height = Fansite.object.outerHeight(),
			y = (offset.top + (nodeHeight / 2)) - (height / 2),
			x;

		if (offset.left > (winWidth * 2))
			x = (offset.left - width) - 10;
		else
			x = offset.left + nodeWidth;

		Fansite.object.show().css({
			top: y,
			left: x + 5
		});
	},

	/**
	 * Generate links for inline display.
	 *
	 * @param target
	 * @param data
	 */
	generate: function(target, data) {
		var links = Fansite.createLinks(Fansite.read(data));

		$(target).html(links.join(' ')).addClass('fansite-group');
	}

};

