(function($) {
    $.fn.otakeSlide = function(pages, options) {
        var defaults = {
            current: location.hash ? location.hash.substring(1) : 1,
            next: '#next',// string, 進むボタンのid
            prev: '#prev',// string, 戻るボタンのid
            pagination: '#pagination',// string, ページ番号を挿入する要素のid
            container: '#slides_container',// string, スライドを挿入する要素のid
            autoHeight: false,// boolean, 高さの自動調節
            currentClass: 'current',// string, 選択されているページ番号のクラス
            pageClass: '',// string, スライドのページのクラス
            isMovePaginator: false,// boolean, ページ番号の表示数制限をするか
            limit: 8,// number, 一度に表示するページ番号の数
            isHeightAnimateNewPage: true,// boolean, ページ作成後にプラグイン側で高さの調節をするかどうか
            pageCreate: function(page) {},// function, ページの作成時に呼び出される関数
            createAfter: function(elment, page) {}// function, ページ作成後に呼び出される関数
        };
        var option = $.extend(defaults, options),
        slideCount = pages,
        containerWidth = $(option.container).width();

        return this.each(function() {
            var ulTag = $('<ul>');
            for(var i = 1; pages >= i; ++i) {
                var liTag = $('<li>').attr({
                    "data-pageNumber": i
                });
                var aTag = $('<a>').attr({
                    "href": "#" + i
                    }).text(i);
                                
                ulTag.append(liTag.append(aTag));
            }
            $(option.pagination).append(ulTag);
            changePaginate();
            if(option.isMovePaginator) {
                movePaginator(option.current);
            }
            if(isValid(option.current)) {
                if(!pageExists(option.current)) {
                    var created = option.pageCreate(option.current-1);
                    var page = $('<div>').attr({
                        "id": option.current + "page"
                        }).addClass(option.pageClass).css({
                        "position": "absolute", 
                        "width": containerWidth
                    }).append(created);
                    $(option.container).append(page);
                    option.createAfter(created, page);
					
                }
				
            }
			
            function pageExists(pageNumber) {
                if($(option.container).find('[id=' + pageNumber + 'page]').size()) {
                    return true;
                } else {
                    return false;
                }
            }
			
            function isValid(pageNumber) {
                if(slideCount >= pageNumber && pageNumber > 0 ) {
                    return true;
                } else {
                    return false;
                }
            }
			
            function next() {
                if(isValid(parseInt(option.current, 10) + 1)) {
                    location.hash = parseInt(option.current, 10) + 1;
                } else {
                    location.hash = 1;
                }
            }
			
            function previous() {
                if(isValid(parseInt(option.current, 10) -1)) {
                    location.hash = option.current - 1;
                } else {
                    location.hash = slideCount;
                }
            }
			
            function changePaginate() {
                if(location.hash) {
                    $(option.pagination + ' li a[href=#' + option.current + ']').closest('li').removeClass(option.currentClass);
                    $(option.pagination + ' li a[href=' + location.hash + ']').closest('li').addClass(option.currentClass);
                } else {
                    $(option.pagination + ' li a[href=#1]').closest('li').addClass(option.currentClass);
                }
                if(option.isMovePaginator) {
                    movePaginator(location.hash.substring(1));
                }
            }
			
            function movePaginator(number) {
                var visiblePage = option.limit;
                //指定されたページが「表示するページ数/2」以下の時
                if(Math.ceil(visiblePage / 2) >= number) {
                    $(option.pagination + ' li').each(function() {
                        if($(this).attr("data-pageNumber") <= visiblePage) {
                            $(this).css({
                                "display": ""
                            });
                        } else {
                            $(this).css({
                                "display": "none"
                            });
                        }
                    });
                //指定されたページが「全てのページ - 表示するページ数/2」より大きい時
                } else if(slideCount - Math.ceil(visiblePage / 2) < number) {
                    $(option.pagination + ' li').each(function() {
                        if($(this).attr('data-pageNumber') > slideCount - visiblePage){
                            $(this).css({
                                "display": ""
                            });
                        } else {
                            $(this).css({
                                "display": "none"
                            });
                        }
                    });
                } else {
                    $(option.pagination + ' li').each(function() {
                        var beforePages = Math.ceil( (visiblePage - 1) / 2);
                        var afterPages = Math.floor( (visiblePage - 1 ) / 2);
                        if($(this).attr('data-pageNumber') >= parseInt(number, 10) - beforePages && $(this).attr('data-pageNumber') <= parseInt(number, 10) + afterPages) {
                            $(this).css({
                                "display": ""
                            });
                        } else {
                            $(this).css({
                                "display": "none"
                            });
                        }
                    });
                }
            }
                        
            $(window).bind('hashchange', function() {
                changePaginate();
                var hash = location.hash.substring(1);
				
                if(isValid(hash)) {
                    if(!pageExists(hash)) {
                        var created = option.pageCreate(hash-1);
                        var page = $('<div>').attr({
                            "id": hash + "page"
                            }).addClass(option.pageClass).css({
                            "position": "absolute", 
                            "width": containerWidth, 
                            "visibility": "hidden"
                        }).append(created);
                        $(option.container).append(page);
                        option.createAfter(created, page);
                        animate(hash, false);
                    } else {

                        animate(hash, true);
                    }
                }
            });
			
            $(option.next).bind('click', function() {
                next();
            });
			
            $(option.prev).bind('click', function() {
                previous();
            });
			
            function animate(page, isReuses) {
                if(parseInt(option.current) < parseInt(page)) {
                    $('#' + option.current + 'page').stop(false,false).animate({
                        "left": -containerWidth + 'px'
                        }, function() {
                        $(this).css("visibility", "hidden");
                    });
                    $('#' + page + 'page').css("visibility", "visible").css('left', containerWidth + 'px').stop(false,false).animate({
                        "left": "0px"
                    });
                } else {
                    $('#' + option.current + 'page').stop(false,false).animate({
                        "left": containerWidth + 'px'
                        }, function() {
                        $(this).css("visibility", "hidden");
                    });
                    $('#' + page + 'page').css("visibility", "visible").css('left', -containerWidth + 'px').stop(false,false).animate({
                        "left": "0px"
                    });						
                }
                option.current = page;

                if(option.autoHeight && isReuses || option.autoHeight && option.isHeightAnimateNewPage) {
                    $(option.container).stop(false, false).animate({
                        'height': $('#' + page + 'page').outerHeight() + 'px'
                        });
                }

            }
        });
    };
})(jQuery);
