(function($) {
	$.fn.filewrap = function(options) {
		var settings = {
			title: '',
			name: undefined,
			placeholder: undefined,
			mouseover: function(){},
			mouseout: function() {},
			id_prefix: '',
			ajax: {
				url: undefined, // string
				secureuri: false,
				success: undefined, // function (data, status, self) {}
				error: undefined, // function (data, status, e) {}
				data: {},
				dataType: 'json'
			},
			returnSelf: false
		};

		if (options) {
			$.extend(options.ajax, settings.ajax);
			$.extend(settings, options);
		}

		var $return = $([]);

		this.each(function(s,i) {
			var self = $(this);

			self.fn = {
				init: function (){
					self.fn.wrapper = (settings.ajax.url == undefined)
							? $('<div/>')
							: $('<form method="POST" enctype="multipart/form-data" action="'+settings.ajax.url+'"/>');

					self.fn.wrapper.css({
						position: 'absolute',
						left: '1000px',
						top: '1000px',
						visibility: 'visible',
						opacity: '0',
						filter:"alpha(opacity=0)"
					});

					self.bind('mousemove', self.fn.divFileShow);
					
					self.fn.wrapper
							.bind('mouseover',settings.mouseover())
							.bind('mouseleave', settings.mouseout())
							.bind('mousemove', self.fn.divFileMove);

					self.fn.ifile = $('<input type="file" tabindex="1" size="1">');

					if (settings.name == undefined) {
						self.fn.ifile.attr('name', self.attr('name'));
						self.removeAttr('name');
					} else {
						self.fn.ifile.attr('name', settings.name);
					}

					if (self.attr('id') != undefined && settings.id_prefix != undefined) {
						self.fn.ifile.attr('id', settings.id_prefix+self.attr('id'));
						if (settings.id_prefix+self.attr('id') == self.attr('id')) self.removeAttr('id');
					}

					self.fn.wrapper.attr('id', 'wrap_'+self.fn.ifile.attr('id'));

					self.fn.ifile.self = self;

					self.fn.ifile.bind('change', function() {
						if (settings.ajax.url != undefined) {

							self.fn.wrapper.ajaxForm({
								data: {'id' : self.fn.ifile.attr('id'), 'X_REQUESTED_WITH': 'xmlhttprequest'},
								beforeSubmit: function(a,f,o) {
									o.dataType = settings.ajax.dataType;
								},
								success: function(data, status) {
									return (settings.ajax.success != undefined)
										? settings.ajax.success(data, status, self)
										: true;
								},
								error: function(data, status, e) {
									return (settings.ajax.error != undefined)
										? settings.ajax.error(data, status, e, self)
										: null;
								}
							});

							self.fn.wrapper.submit();
						}

						self.fn.result();
					});


					self.fn.wrapper.append(self.fn.ifile);
					self.before(self.fn.wrapper);
				},

				ifile:undefined,
				wrapper: undefined,

				limitXMin: 0,
				limitXMax: 0,
				limitYMin: 0,
				limitYMax: 0,

				mouseX: function (e) {
					if (e.pageX) return e.pageX;
					if (e.clientX) return e.clientX + document.body.scrollLeft;
				},
				mouseY: function (e) {
					if(e.pageY) return e.pageY;
					if(e.clientY) return e.clientY + document.body.scrollTop;
				},
				getPos: function () {
					var left = self.offset().left;
					var top = self.offset().top;
					return {left: left, top: top, width: parseInt(self.width()), height: parseInt(self.height())};
				},

				divFileShow: function (e) {
					self.fn.limitXMin = parseInt(self.offset().left);
					self.fn.limitXMax = self.fn.limitXMin + self.outerWidth();
					self.fn.limitYMin = parseInt(self.offset().top);
					self.fn.limitYMax = self.fn.limitYMin + self.outerHeight();
					
					self.fn.wrapper.css({
						'left': (self.fn.mouseX(e) - Math.round(self.fn.wrapper.width()/2)) + "px",
						'top': (self.fn.mouseY(e) - Math.round(self.fn.wrapper.height()/2)) + "px",
						visibility: "visible"
					});
				},

				divFileMove: function (e) {

					var move = true;

					var posX = parseInt(self.fn.mouseX(e));
					var posY = parseInt(self.fn.mouseY(e));

					if (self.fn.limitXMin > posX || posX > self.fn.limitXMax) {
						move = false;
					}
					if (self.fn.limitYMin > posY || posY > self.fn.limitYMax){
						move = false;
					}

					if (move){
						self.fn.wrapper.css({
							left: (self.fn.mouseX(e) - self.fn.wrapper.width()/2) + "px",
							top: (self.fn.mouseY(e) - self.fn.wrapper.height()/2) + "px"
						});
					}
					else {
						self.fn.wrapper.css('visibility', "hidden");
					}
				},
				result: function () {
					var target = (settings.title != '') ? $(settings.title) : self;

					var value = self.fn.ifile.val().replace(/^([^\\\/]*(\\|\/))*/,"");

					if (settings.placeholder != undefined) {
						value = settings.placeholder.replace('%%', value);
					}

					var tag = target[0].tagName.toLowerCase();

					if (tag == 'input') {
						$(target).val(value);
					} else {
						$(target).text(value);
					}


					self.attr("title",self.fn.ifile.val());
				}
			};
			self.fn.init();

			$return = $return.add((settings.returnSelf) ? self : self.fn.ifile);
		});

		return $return;
	};
	$.fn.wrapFile = function(options) {
		return this.each(function() {
			var defaults, o, self, $self, i;
			defaults = {
				url: '',
				file: 'file',
				placeholder: '',
				data: {
					'X_REQUESTED_WITH' : 'XMLHttpRequest'
				}
//				bind: {
//					mouseover: function() {},
//					mouseout: function() {},
//					click: function() {},
//					change: function() {}
//				}
			};
			o = $.extend(true, defaults, options);
			self = this;
			$self = $(self);
//			self.file = $('<input type="file" name="file" id="file" class="file" size="1" style="-moz-opacity: 0;  filter: alpha(opacity=0); opacity: 0;"/>');
			self.file = document.createElement('input');
			self.file.type = 'file';
			self.file.name = o.name;
			self.file.id = 'input-file-' + this.id;
			self.file.size = '1';
			self.file.style['MozOpacity'] = '0';
			self.file.style['filter'] = 'alpha(opacity=0)';
			self.file.style['opacity'] = '0';

			if (o.url.length) {
				self.wrapper = document.createElement('form');
				self.wrapper.method = 'POST';
				self.wrapper.enctype = 'multipart/form-data';
				self.wrapper.action = o.url;
			} else {
				self.wrapper = document.createElement('div');
			}
			self.wrapper.style.overflow = 'hidden';
			function resize() {
				var w,h;
				w = $self.outerWidth();
				h = $self.outerHeight();
				self.wrapper.style.width = w + 'px';
				self.wrapper.style.height = h + 'px';
//				var css = {};
//				if (h > w) {
//					css.fontSize = h*2;
//				} else {
//					css.fontSize = w*2;
//				}
//				css.height = h*2;
//				css.marginTop = -h;
//				css.marginLeft = -(css.fontSize*3+css.fontSize/10);
//				self.file.css(css);

				var fontSize = (h > w) ? h*2 : w*2;
				self.file.style['fontSize'] = fontSize + 'px';
				self.file.style['height'] = (h*2) + 'px';
				self.file.style['marginTop'] = '-' + h + 'px';
				self.file.style['marginLeft'] = '-' + (fontSize*3+fontSize/10) + 'px';

			}
			$(this).load(resize);
			if (!o.placeholder.length) o.placeholder = $self.data('placeholder') || '';
			if (o.placeholder.length) {
				$(self.file).bind('change', function() {
					var val = o.placeholder.replace('%%', $(this).val().replace(/(C:\\(.*)\\)/igm, ''));
					if ($self[0].nodeName.toLowerCase() == 'input') {
						$self.attr('value', val);
					} else {
						$self.text(val);
					}
					resize();
				});
			}
			for (i in o.data) {
				var el = document.createElement('input');
				el.type='hidden';
				el.name=i;
				el.value=o.data[i];
				self.wrapper.appendChild(el);
			}
			$(self.wrapper).appendTo($self.parent()).append(self).append(self.file);
			for (i in o.bind) {
				$(self.file).bind(i, function(event) {
					return o.bind[i].apply(self, [event, self.file, self.wrapper]);
				});
			}
			return this;
		});
	};
})(jQuery);

