(function($) {
    $.fn.scaleeffectWS = function(exOptions, reOption, center) {
        var exOptions = $.extend({duration: "slow", easing: 'easeOutBounce'}, exOptions || {});
        var reOption = $.extend({duration: "slow", easing: 'easeOutBounce'}, reOption || {});
        var center = center || false;
        var srcelems = this;
        var targetelems = [];
        var drag = function(handle, dragelem) {
            handle.mousedown(function(event) {
                handle.stoped = true;
                event.preventDefault();
                event.stopPropagation();
                handle.last = $(document.body).children().filter(':last')[0] == dragelem[0];
                if (!handle.last) dragelem.parent().append(dragelem);
                var dx = parseInt(dragelem.css('left')) - event.pageX;
                var dy = parseInt(dragelem.css('top')) - event.pageY;
                $(document).mousemove(function(event) {
                    event.preventDefault();
                    event.stopPropagation();
                    handle.stoped = false;
                    dragelem.css({
                        left: (event.pageX + dx),
                        top: (event.pageY + dy)
                    });
                    handle.css({cursor: 'move'});
                });
                $(document).mouseup(function(event) {
                    $(document).unbind('mousemove');
                    handle.css({cursor: 'pointer'});
                });
            });
        };
        var moved = false;
        return this.each(function(idx, srcelem){
            targetelems.push($('<img class="largeImg">'));
            var listener = function(event) {
                var largeImg;
                var smallImg = $(srcelems[idx]).children();
                var sWidth = smallImg.width();
                var sHeight = smallImg.height();
                var sTop = smallImg.offset().top;
                var sLeft = smallImg.offset().left;
                var sAttr = {width: sWidth, height: sHeight, top: sTop, left: sLeft};

                if (event.type == 'keydown') {
                    if ($(document.body).children().filter(':last')[0] != targetelems[idx].parent()[0]) return;
                    var k = event.keyCode;
                    if (k == 39 || k == 37 || k == 40) {
                        event.preventDefault();
                        event.stopPropagation();
if (moved) return;
moved = true;
                        var lAttr = {
                            top: targetelems[idx].offset().top,
                            left: targetelems[idx].offset().left
                        }
                        targetelems[idx].parent().remove();
                        targetelems[idx].appendTo($(document.body)).css(lAttr);
                        targetelems[idx].animate(sAttr, $.extend(reOption, {complete: function(){targetelems[idx].removeAttr('style').remove();srcelems.eq(idx).children().css({visibility: 'visible'});moved = false;}}));
                        if (event.keyCode == 39) {
                            smallImg = $(srcelems.length - 1 == idx? srcelems[0]: srcelems[idx + 1]).children();
                            largeImg = targetelems.length - 1 == idx? targetelems[0]: targetelems[idx + 1];
                        } else if (event.keyCode == 37) {
                            smallImg = $(0 == idx? srcelems[srcelems.length - 1]: srcelems[idx - 1]).children();
                            largeImg = 0 == idx? targetelems[targetelems.length - 1]: targetelems[idx - 1];
                        } else return;
                    } else return;
                } else {
                    event.preventDefault();
                    event.stopPropagation();
if (moved) return;
moved = true;
                    if (event.target.moved) return;
                    largeImg = targetelems[idx];
                }
                if (largeImg.parent()[0]) largeImg.parent().remove();
                sAttr.top = smallImg.offset().top;
                sAttr.left = smallImg.offset().left;
                largeImg.appendTo($(document.body));
                largeImg.attr('src', smallImg.parent().attr('href'));
                var execution = function() {
                    var width = largeImg.width();
                    var height = largeImg.height();
                    var top;
                    var left;
                    if (center) {
                        top = ($(window).height() - largeImg.outerHeight()) / 2 + $(window).scrollTop();
                        left = ($(window).width() - largeImg.outerWidth()) / 2 + $(window).scrollLeft();                    
                    } else {
                        var totalHeight = $(window).height() + $(window).scrollTop();
                        var totalWidth = $(window).width() + $(window).scrollLeft();
                        var posT = sAttr.top - height / 2 + sAttr.height / 2;
                        var posL = sAttr.left - width / 2 + sAttr.width / 2;
                        top = (totalHeight < sAttr.top + sAttr.height + height / 2)? Math.min(posT, totalHeight - largeImg.outerHeight() - 20): Math.max(posT, 20 + $(window).scrollTop());
                        left = (totalWidth < sAttr.left + sAttr.width + width / 2)? Math.min(posL, totalWidth - largeImg.outerWidth() - 20): Math.max(posL, 20 + $(window).scrollLeft());
                    }
                    var lAttr = {width: width, height: height, top: top, left: left};
                    largeImg.css(sAttr).animate(lAttr, $.extend(exOptions, {
                        complete: function() {
                            largeImg.shadow2(4, 'img/default/');
                            drag(largeImg, largeImg.parent());
moved = false;
                            largeImg.click(function(event) {
                                if (!largeImg.stoped || !largeImg.last) return;
                                lAttr.top = largeImg.offset().top;
                                lAttr.left = largeImg.offset().left;
                                largeImg.parent().remove();
                                largeImg.appendTo($(document.body)).css(lAttr);
                                sAttr.top = smallImg.offset().top;
                                sAttr.left = smallImg.offset().left;
                                largeImg.animate(sAttr, $.extend(reOption, {complete: function(){largeImg.removeAttr('style').remove(); smallImg.css({visibility: 'visible'});moved = false;}}));
                            });
                        }
                    }));
                    smallImg.css({visibility: 'hidden'});
                };
                if (largeImg[0].complete) execution();
                else {
                    largeImg.load(function(event) {execution()});
                }
            };
            $(srcelem).click(listener);
            $(document).keydown(listener);
        });
    };
})(jQuery);
