/*
 * artZoom 1.0.7
 * Date: 2011-06-22
 * (c) 2009-2011 TangBin, http://www.planeArt.cn
 *
 * This is licensed under the GNU LGPL, version 2.1 or later.
 * For details, see: http://creativecommons.org/licenses/LGPL/2.1/
 */
(function (document, $, log) {

$.fn.artZoom = function (config) {
	config = $.extend({}, $.fn.artZoom.defaults, config);
	
	var tmpl, viewport,
		$this = this,
		loadImg = {},
		path = config.path,
		loading = path + '/loading.gif',
		max = path + '/zoomin.cur',
		min = path + '/zoomout.cur';
	
	new Image().src = loading;
	
	max = 'url(\'' + max + '\'), pointer';
	min = 'url(\'' + min + '\'), pointer';
	
	tmpl = [
		'<div class="ui-artZoom-toolbar" style="display:none">',
			'<span class="ui-artZoom-buttons" style="display:none">',
				'<a href="#" data-go="left" class="ui-artZoom-left"><span></span>',
					config.left,
				'</a>',
				'<a href="#" data-go="right" class="ui-artZoom-right"><span></span>',
					config.right,
				'</a>',
				'<a href="#" data-go="source" class="ui-artZoom-source"><span></span>',
					config.source,
				'</a>',
				'<a href="#" data-go="hide" class="ui-artZoom-hide"><span></span>',
					config.hide,
				'</a>',
			'</span>',
			'<span class="ui-artZoom-loading">',
				'<img data-live="stop" src="',
					loading,
					'" style="',
					'display:inline-block;*zoom:1;*display:inline;vertical-align:middle;',
					'width:16px;height:16px;"',
				' />',
				' <span>Loading..</span>',
			'</span>',
		'</div>',
		'<div class="ui-artZoom-box" style="display:none">',
			'<span class="ui-artZoom-photo" data-go="hide"',
			' style="display:inline-block;*display:inline;display:block\0;*zoom:1;overflow:hidden;position:relative;cursor:',
				min,
			'">',
				'<img data-name="thumb" data-go="hide" data-live="stop" src="',
					loading,
				'" />',
			'</span>',
		'</div>'
	].join('');
	
	// jQuery事件代理
	this.on('click', function (event) {
		if (this.nodeName !== 'IMG' && this.getAttribute('data-live') === 'stop') return false;
		
		var $artZoom, buttonClick,
			that = this,
			$this = $(that),
			$parent = $this.parent(),
			src = that.src,
			show = $this.attr('data-artZoom-show') || src,
			source = $this.attr('data-artZoom-source') || show,
			maxWidth = config.maxWidth || ($parent[0].nodeName === 'A' ? $this.parent() : $this).parent().width(),
			maxHeight = config.maxHeight || 99999;
		
		maxWidth = maxWidth - config.borderWidth;
		
		// 对包含在链接内的图片进行特殊处理
		if ($parent[0].nodeName === 'A') {
			show = $parent.attr('data-artZoom-show') || $parent.attr('href');
			source = $parent.attr('data-artZoom-source') || $parent.attr('rel');
		};

		// 第一次点击
		if (!$this.data('artZoom')) {
			var wrap = document.createElement('div'),
				$thumb, $box, $show;
			
			$artZoom = $(wrap);
			wrap.className = 'ui-artZoom ui-artZoom-noLoad';
			wrap.innerHTML = tmpl;
			
			($parent[0].nodeName === 'A' ? $this.parent() : $this).before(wrap);
			$this.data('artZoom', $artZoom);
			$box = $artZoom.find('.ui-artZoom-box');
			$thumb = $artZoom.find('[data-name=thumb]');
			
			// 快速获取大图尺寸
			imgReady(show, function () {
				var width = this.width,
					height = this.height,
					maxWidth2 = Math.min(maxWidth, width);
				
				height = maxWidth2 / width * height;
				width = maxWidth2;
				
				// 插入大图并使用逐渐清晰加载的效果
				$thumb.attr('src', src).
					css(config.blur ? {
						width: width + 'px',
						height: height + 'px'
					} : {display: 'none'}).
					after([
					'<img class="ui-artZoom-show" title="',
						that.title,
						'" alt="',
						that.alt,
						'" src="',
						show,
						'" style="width:',
						width,
						'px;height:',
						height, // IE8 超长图片height属性失效BUG，改用CSS
						'px;position:absolute;left:0;top:0;background:transparent"',
					' />'
				].join(''));
				
				$show = $artZoom.find('.ui-artZoom-show');
				$thumb.attr('class', 'ui-artZoom-show');
				
				$artZoom.addClass('ui-artZoom-ready');
				$artZoom.find('.ui-artZoom-buttons').show();
				$this.data('artZoom-ready', true);
				$this.hide();
				$box.show();
				
			// 大图完全加载完毕
			}, function () {
				$thumb.removeAttr('class').hide();
				$show.css({
					position: 'static',
					left: 'auto',
					top: 'auto'
				});
				
				$artZoom.removeClass('ui-artZoom-noLoad');
				$artZoom.find('.ui-artZoom-loading').hide();
				$this.data('artZoom-load', true);
			
			// 图片加载错误
			}, function () {
				$artZoom.addClass('ui-artZoom-error');
				log('jQuery.fn.artZoom: Load "' + show + '" Error!');
			});
			
		} else {
			$this.hide();
		};
		
		$artZoom = $this.data('artZoom');
		buttonClick = function (event) {
			var target = this,
				go = target.getAttribute('data-go'),
				live = target.getAttribute('data-live'),
				degree = $this.data('artZoom-degree') || 0,
				elem = $artZoom.find('.ui-artZoom-show')[0];
				
			if (live === 'stop') return false;
			if (/img|canvas$/i.test(target.nodeName)) go = 'hide';
			
			switch (go) {
				case 'left':
					degree -= 90;
					degree = degree === -90 ? 270 : degree;
					break;
				case 'right':
					degree += 90;
					degree = degree === 360 ? 0 : degree;
					break;
				case 'source':
					window.open(source || show || src);
					break;
				case 'hide':
					$this.show();
					$artZoom.find('.ui-artZoom-toolbar').hide();
					$artZoom.hide();
					$artZoom.find('[data-go]').die('click', buttonClick);
					break;
			};
			
			if ((go === 'left' || go === 'right') && $this.data('artZoom-load')) {
				imgRotate(elem, degree, maxWidth, maxHeight);
				$this.data('artZoom-degree', degree);
			};
			
			return false;
		};
		$artZoom.show().find('.ui-artZoom-toolbar').slideDown(150);
		$artZoom.find('[data-go]').on('click', buttonClick);
			
		return false;
	});
	
	// 给目标缩略图应用外部指针样式
	this.on('mouseover', function () {
		if (this.className !== 'ui-artZoom-show') this.style.cursor = max;
	});
	
	// 预加载指针形状图标
	if (this[0]) this[0].style.cursor = max;
	
	return this;
};
$.fn.artZoom.defaults = {
	path: './images',
	left: '\u5de6\u65cb\u8f6c',
	right: '\u53f3\u65cb\u8f6c',
	source: '\u770b\u539f\u56fe',
	hide: '\xd7',
	blur: true,
	preload: true,
	maxWidth: null,
	maxHeight: null,
	borderWidth: 18
};

/**
 * 图片旋转
 * @version	2011.05.27
 * @author	TangBin
 * @param	{HTMLElement}	图片元素
 * @param	{Number}		旋转角度 (可用值: 0, 90, 180, 270)
 * @param	{Number}		最大宽度限制
 * @param	{Number}		最大高度限制
 */
var imgRotate = $.imgRotate = function () {
	var eCanvas = '{$canvas}',
		isCanvas = !!document.createElement('canvas').getContext;
		
	return function (elem, degree, maxWidth, maxHeight) {
		var x, y, getContext,
			resize = 1,
			width = elem.naturalWidth,
			height = elem.naturalHeight,
			canvas = elem[eCanvas];
		
		// 初次运行
		if (!elem[eCanvas]) {
			
			// 获取图像未应用样式的真实大小 (IE和Opera早期版本)
			if (!('naturalWidth' in elem)) {
				var run = elem.runtimeStyle, w = run.width, h = run.height;
				run.width  = run.height = 'auto';
				elem.naturalWidth = width = elem.width;
				elem.naturalHeight = height = elem.height;
				run.width  = w;
				run.height = h;
			};
		
			elem[eCanvas] = canvas = document.createElement(isCanvas ? 'canvas' : 'span');
			elem.parentNode.insertBefore(canvas, elem.nextSibling);
			elem.style.display = 'none';
			canvas.className = elem.className;
			canvas.title = elem.title;
			if (!isCanvas) {
				canvas.img = document.createElement('img');
				canvas.img.src = elem.src;
				canvas.appendChild(canvas.img);
				canvas.style.cssText = 'display:inline-block;*zoom:1;*display:inline;' +
					// css reset
					'padding:0;margin:0;border:none 0;position:static;float:none;overflow:hidden;width:auto;height:auto';
			};
		};
		
		var size = function (isSwap) {
			if (isSwap) width = [height, height = width][0];
			if (width > maxWidth) {
				resize = maxWidth / width;
				height =  resize * height;
				width = maxWidth;
			};
			if (height > maxHeight) {
				resize = resize * maxHeight / height;
				width = maxHeight / height * width;
				height = maxHeight;
			};
			if (isCanvas) (isSwap ? height : width) / elem.naturalWidth;
		};
		
		switch (degree) {
			case 0:
				x = 0;
				y = 0;
				size();
				break;
			case 90:
				x = 0;
				y = -elem.naturalHeight;
				size(true);
				break;
			case 180:
				x = -elem.naturalWidth;
				y = -elem.naturalHeight
				size();
				break;
			case 270:
				x = -elem.naturalWidth;
				y = 0;
				size(true);
				break;
		};
		
		if (isCanvas) {
			canvas.setAttribute('width', width);
			canvas.setAttribute('height', height);
			getContext = canvas.getContext('2d');
			getContext.rotate(degree * Math.PI / 180);
			getContext.scale(resize, resize);
			getContext.drawImage(elem, x, y);	
		} else {
			canvas.style.width = width + 'px';
			canvas.style.height = height + 'px';// 解决IE8使用滤镜后高度不能自适应
			canvas.img.style.filter = 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + degree / 90 + ')';
			canvas.img.width = elem.width * resize;
			canvas.img.height = elem.height * resize;
		};
	};
}();

/**
 * 图片头数据加载就绪事件 - 更快获取图片尺寸
 * @version	2011.05.27
 * @author	TangBin
 * @see		http://www.planeart.cn/?p=1121
 * @param	{String}	图片路径
 * @param	{Function}	尺寸就绪
 * @param	{Function}	加载完毕 (可选)
 * @param	{Function}	加载错误 (可选)
 * @example imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
		alert('size ready: width=' + this.width + '; height=' + this.height);
	});
 */
var imgReady = (function () {
	var list = [], intervalId = null,

	// 用来执行队列
	tick = function () {
		var i = 0;
		for (; i < list.length; i++) {
			list[i].end ? list.splice(i--, 1) : list[i]();
		};
		!list.length && stop();
	},

	// 停止所有定时器队列
	stop = function () {
		clearInterval(intervalId);
		intervalId = null;
	};

	return function (url, ready, load, error) {
		var onready, width, height, newWidth, newHeight,
			img = new Image();
		
		img.src = url;

		// 如果图片被缓存，则直接返回缓存数据
		if (img.complete) {
			ready.call(img);
			load && load.call(img);
			return;
		};
		
		width = img.width;
		height = img.height;
		
		// 加载错误后的事件
		img.onerror = function () {
			error && error.call(img);
			onready.end = true;
			img = img.onload = img.onerror = null;
		};
		
		// 图片尺寸就绪
		onready = function () {
			newWidth = img.width;
			newHeight = img.height;
			if (newWidth !== width || newHeight !== height ||
				// 如果图片已经在其他地方加载可使用面积检测
				newWidth * newHeight > 1024
			) {
				ready.call(img);
				onready.end = true;
			};
		};
		onready();
		
		// 完全加载完毕的事件
		img.onload = function () {
			// onload在定时器时间差范围内可能比onready快
			// 这里进行检查并保证onready优先执行
			!onready.end && onready();
		
			load && load.call(img);
			
			// IE gif动画会循环执行onload，置空onload即可
			img = img.onload = img.onerror = null;
		};

		// 加入队列中定期执行
		if (!onready.end) {
			list.push(onready);
			// 无论何时只允许出现一个定时器，减少浏览器性能损耗
			if (intervalId === null) intervalId = setInterval(tick, 40);
		};
	};
})();

}(document, jQuery, function (msg) {window.console && console.log(msg)}));
