jQuery.fn.extend({
    createGallery: function () {
        //core
        $gallery = function (jEl, options) {
            var parent = this;
            this.showZone = $(options.showZone);
            this.list = jEl;
            this.items = this.list.find("> li > a");
            this.wrapper = $("<div class=\"GalleryItemsContainer\"></div>");
            this.list.before(this.wrapper);
            this.wrapper.append(this.list);
            /*control*/
            this.next = $("<a href=\"#\" title=\"Next\" class=\"ControlBtn NextBtn\">Next</a>");
            this.prev = $("<a href=\"#\" title=\"Previous\" class=\"ControlBtn PrevBtn\">Previous</a>");
            this.controlWrapper = $("<div class=\"GalleryControlContainer\"></div>");
            this.wrapper.before(this.controlWrapper);
            this.controlWrapper.append(this.wrapper);
            this.controlWrapper.prepend(this.next);
            this.controlWrapper.prepend(this.prev);
            this.timer;
            //control events
            //next
            this.next.bind("mousedown", function () {
                parent.timer = setInterval(function () {
                    parent.updateBtnStatus();
                    if ( parent.list.width() + parent.list.position().left - parent.wrapper.width() - parseInt(parent.items.parent().eq(0).css("paddingRight")) > 0 ) {
                        parent.list.css({
                            left: parent.list.position().left - options.offset
                        });
                    }
                    else {
                        clearInterval(parent.timer);
                    }
                }, 10);
            });
            this.next.bind("mouseup", function () {
                clearInterval(parent.timer);
            });
            //prev
            this.prev.bind("mousedown", function () {
                parent.timer = setInterval(function () {
                    parent.updateBtnStatus();
                    if ( parent.list.position().left < 0 ) {
                        parent.list.css({
                            left: parent.list.position().left + options.offset
                        });
                    }
                    else {
                        clearInterval(parent.timer);
                    }
                }, 10);
            });
            this.prev.bind("mouseup", function () {
                clearInterval(parent.timer);
            });

            this.listWidth = 0;
            this.items.each(function () {
                var self = $(this);
                var imgURL = self.attr("href");
                parent.listWidth += self.parent().outerWidth();
                //events
                self.bind("click", function () {
                    parent.list.find("li.Active").removeClass("Active");
                    self.parent().addClass("Active");
                    parent.showZone.empty();
                    parent.loadImage(imgURL);
                    return false;
                });
            });
            this.list.css({
                width: this.listWidth,
                height: this.items.parent().eq(0).outerHeight(),
                position: "absolute",
                left: 0,
                top: 0
            });

            //methods
            this.loadImage = function (imgURL) {
                parent.showZone.addClass("ShowcaseLoading");
                try {
                    this.showZone.empty();
                    var img = new Image();
                    img.onload = function () {
                        img.width = parent.showZone.width();
                        img.height = parent.showZone.height();
                        $(img).hide().appendTo(parent.showZone);
                        parent.showZone.removeClass("ShowcaseLoading");
                        $(img).fadeIn("slow");
                    }
                    img.onerror = function () {
                        parent.showZone.append("<p class=\"ErrorMessage\">Can not load image !</p>")
                    }
                    img.src = imgURL;
                }
                catch (err) {
                    //error exception
                }
                return this;
            }
            this.updateBtnStatus = function () {
                if ( parent.list.width() + parent.list.position().left - parent.wrapper.width() - parseInt(parent.items.parent().eq(0).css("paddingRight")) > 0 ) {
                    this.next.removeClass("Disable");
                }
                else {
                    this.next.addClass("Disable");
                }

                if ( parent.list.position().left < 0 ) {
                    this.prev.removeClass("Disable");
                }
                else {
                    this.prev.addClass("Disable");
                }

                return this;
            }

            /*default loading*/
            //this.loadImage( this.items.eq(0).attr("href") );
            this.updateBtnStatus();
        }

        //setup
        options = arguments[0];
        var galleryManager = [];
        this.each(function () {
            galleryManager["#" + $(this).attr("id")] = ( new $gallery($(this), options) );
        });

        return galleryManager;
    }
});