(function($){
	$.preloadImage = function(image, callback) {
		var self = this;
		this.file = image;
		this.callback = callback;
		this.loaded = false;
		this.aborted = false;
		this.error = false;
		this.image = new Image();
		
		this.cancelEvent = function() {
			if (this.image && this.image.onload) {
				this.image.onload = null;
			}
			if (this.image && this.image.onabort) {
				this.image.onabort = null;
			}
			if (this.image && this.image.onerror) {
				this.image.onerror = null;
			}
			this.image = null;
		};
		
		this.on_load = function() {
			self.loaded = true;
			if (self.callback && typeof self.callback == "function") {
				self.callback.apply(self, [self, "loaded"]);
			}
			self.cancelEvent();
		};
		
		this.on_error = function() {
			self.error = true;
			if (self.callback && typeof self.callback == "function") {
				self.callback.apply(self, [self, "error"]);
			}
			self.cancelEvent();
		};
		
		this.on_abort = function() {
			self.aborted = true;
			if (self.callback && typeof self.callback == "function") {
				self.callback.apply(self, [self, "aborted"]);
			}
			self.cancelEvent();
		};
		
		this.image.src = this.file;
		
		this.autoCheckIntervalId = 0;
		this.autoCheck = function() {
			if (self.loaded || self.aborted || self.error) {
				window.clearInterval(self.autoCheckIntervalId);
				return;
			}
			
			if (self.image && self.image.complete) {
				window.clearInterval(self.autoCheckIntervalId);
				self.loaded = true;
				if (self.callback && typeof self.callback == "function") {
					self.callback.apply(self, [self, "loaded"]);
				}
				self.cancelEvent();
				return;
			}
			
			if (self.image && (self.image.width || self.image.height)) {
				window.clearInterval(self.autoCheckIntervalId);
				self.loaded = true;
				if (self.callback && typeof self.callback == "function") {
					self.callback.apply(self, [self,  "loaded"]);
				}
				self.cancelEvent();
				return;
			}
		};
		
		this.autoCheckIntervalId = window.setInterval( self.autoCheck, 500 );
	};
})(jQuery);

(function($){
	$.fn.photoSlides = function(options){
		var isMethodCall = (typeof options == "string"),
			args = Array.prototype.slice.call(arguments, 1);
			
		return this.each(function() {
			var instance = $(this).data("photoSlides");
			if (isMethodCall && instance && $.isFunction(instance[options])) {
				instance[options].apply(instance, args);
			} else if (!instance) {
				$(this).data("photoSlides", new $.photoSlides(this, options));
			}
		});
	};
	
	var deg2radians = Math.PI * 2 / 360;
	var rmatrix = /progid\:DXImageTransform\.Microsoft\.Matrix\([^)]*\)/i;
	
	
	function fnSetRotation(oObj, deg)
	{    
		rad = deg * deg2radians ;
		costheta = Math.cos(rad);
		sintheta = Math.sin(rad);
		
		/*
		oObj.filters.item(0).M11 = costheta;
		oObj.filters.item(0).M12 = -sintheta;
		oObj.filters.item(0).M21 = sintheta;
		oObj.filters.item(0).M22 = costheta;
		*/
		
		
		var style = oObj.style;

			// Set the alpha filter to set the opacity
			var matrix = "progid:DXImageTransform.Microsoft.Matrix(M11='" + costheta + "', M12='"+(-sintheta)+"', M21='"+sintheta+"', M22='"+costheta+"', DX='0', DY='0', sizingmethod='auto expand')",
				filter = style.filter || "";
				
			

			style.filter = rmatrix.test(filter) ?
				filter.replace(rmatrix, matrix) :
				style.filter + ' ' + matrix;
				
			//console.log(style.filter);
			//console.log('xx');

	}
	
	var PhotoSlides = $.photoSlides = function(element, options) {
		this.element = $(element);
		this.options = $.extend(true, {},$.photoSlides.defaults, options);
		this.init();
	};
	
	$.extend($.photoSlides.prototype, {
		init: function() {
			var self = this;
			this.slides = [];
			this.started = false;
			
			if ( typeof this.options.width !== "undefined" && typeof this.options.height !== "undefined" && typeof this.options.photos !== "undefined" ) {
				if ( this.options.width > 0 && this.options.height > 0 && $.isArray(this.options.photos) && this.options.photos.length ) {
					
					this.element.addClass("photoSlides");
					if ( $.browser.msie ) {
						this.element.addClass("photoSlidesIE");
					}
					$("<div class='loading'></div>").appendTo(this.element);
					
					for (var i = 0, n = this.options.photos.length; i < n; i++) {
						var obj;
						this.options.photos[i].loaded = false;
						obj = new $.preloadImage(this.options.photos[i], function(obj, status) {
							self.options.photos[obj.idx].loaded = true;
							if (status == "loaded") {
								self.imageLoaded(obj);
								obj = null;
							}
						});
						obj.idx = i;
					}
				}
			}
		},
		
		setTimeout: function() {
			var self = this;
			
			this.timeout = window.setTimeout(function(){
				self.nextSlide();
			}, this.options.slideInterval);
			
		},
		
		imageLoaded: function(obj){
			var p = this.options.photos[obj.idx], self = this, allLoaded = true;
			this.createSlide(p.src, p.rotate || 0);
			
			for (var i = 0, n = this.options.photos.length; i < n; i++) {
				if ( !this.options.photos[i].loaded ) {
					allLoaded = false;
					break;
				}
			}
			
			if ( allLoaded ) {
				if ( !this.started ) {
					
					window.setTimeout(function() {
						$(">.loading", self.element).hide();
						
						self.started = true;
						self.slides[0].css("visibility", "visible");
						
						self.curIdx = 0;
						self.setTimeout();
						self = null;
					}, 1000);
				}
			}
			
			p = null;
		},
		
		nextSlide: function() {
			var idx = typeof this.curIdx !== "undefined" ? this.curIdx : -1,
				slide;
				
			if ( this.slides.length < 2 || idx < 0 ) {
				return;
			}
			
			idx = (idx + 1) % this.slides.length;
			
			slide = this.slides[idx];
			
			slide.stop().appendTo(this.element).css({
				opacity: this.options.fromOpacity,
				top: this.options.fromTop,
				left: this.options.fromLeft
			}).animate({left:0, top:0, opacity:1}, {duration:this.options.anim_duration, easing: this.options.anim_easing});
			
			this.curIdx = idx;
			
			this.setTimeout();
		},
		
		init_ie:function(slide, rotate){
			var 
				w, h, w0, h0,
				x1, x2, y1, y2
				r = rotate * deg2radians ;
			w = this.options.width;
			h = this.options.height;
			
			//inner shift width
			x1 = h * Math.abs(Math.sin(r));
			
			//outer shift width
			x2 = w * Math.abs(Math.cos(r));
			
			w0 = (x1 + x2) - w;
			
			//inner shift height
			y1 = h * Math.abs(Math.cos(r));
			
			//outer shift height
			y2 = w * Math.abs(Math.sin(r));
			
			h0 = (y1 + y2) - h;
			
			slide.css({
				marginTop: -h0/2,
				marginLeft: -w0/2
			});
		},
		
		createSlide: function(src, rotate) {
			/*
			var slide = $("<div class='photoSlide' style='visibility:hidden;'><div class='holder' style='width:" + this.options.width + "px; height: " + this.options.height + "px;'>" +
				"<img src='" + src + "' alt=''></div></div>");
			*/
			var slide = $("<div class='photoSlide' style='width:" + this.options.width + "px; height: " + this.options.height + "px;'>" +
				"<img src='" + src + "' alt='' width='"+this.options.width+"' height='"+this.options.height+"'></div>"), w, h, w0, h0, x, y;
			
			this.slides.push(slide);
			this.element.append(slide);
			
			slide.css({
				"rotation": rotate + "deg",
				"-webkit-transform": "rotate(" + rotate + "deg)",
				"-moz-transform": "rotate(" + rotate + "deg)",
				"opacity": 1,
				"filter": "progid:DXImageTransform.Microsoft.Matrix(M11='1.0', sizingmethod='auto expand')"
			});
			
			if ( rotate !== 0 ) {
				slide.addClass("rotated");
				
				if ( $.browser.msie ) {
					//adjust to center
					this.init_ie(slide, rotate);
					fnSetRotation(slide[0], rotate);
					
				}
			}
		}
	});
	
	$.extend($.photoSlides, {
		defaults: {}
	});
})(jQuery);
