
(function($) {

    $.fn.imageLoadAndCall = function (url,callback) {
        if (this.complete) {
            callback.call(this);
            return this;
        }
        var suffix = '';
        if ($.browser.msie) { //IE
            suffix = '?rd='+(new Date()).getTime();//fetch every time
            if (url==null && this.data('fromJson'))
                url = this.attr('src');//URL
        }
        this.load(function() {callback.call(this);});
        if (url) this.attr('src',url+suffix); 
        //IEは後でセットしないとイベント出ない！&& IEは戻るボタンなどではイベント出ない！
        return this;
    };

    $.fn.bannerGallery = function (options) {
        var settings = {
            scaling : "fit", // or fill, none
            imageId : "image-container",
            duration : 3.0,
            thmScaling  : "fill", // or fit, none
            thmDarkness : 0.5,
            thmDuration : 0.4,
            textId : "",
            interval : 0,
            json : null
        };
        if (options) $.extend(settings,options);
        settings.duration = settings.duration * 1000;
        settings.thmDuration = settings.thmDuration * 1000;
        settings.interval = settings.interval * 1000;
        
        var prepare = {
            _scaleAndLayout: function ($img, scaling, width, height) {
                var ratioX, ratioY, scale, newW, newH, orgW, orgH;
                orgW = $img.width();
                orgH = $img.height();
                ratioX = width / orgW;
                ratioY = height / orgH;
                if (scaling === 'fit') {
                    scale = ratioX < ratioY ? ratioX : ratioY;
                } else if (scaling === 'fill') {
                    scale = ratioX > ratioY ? ratioX : ratioY;
                } else {
                    scale = 1.0;
                }
                newW = parseInt(orgW * scale);
                newH = parseInt(orgH * scale);      
                $img.css({
                    "width": newW + "px",
                    "height": newH + "px",
                    "position": "absolute",
                    "top": (parseInt((height - newH) / 2)) + "px",
                    "left": (parseInt((width - newW) / 2)) + "px"
                }).attr({
                    "width": newW,
                    "height": newH
                });
            },
            //----- 1st
            createThumbnail: function ($img) {
                prepare._scaleAndLayout($img, settings.thmScaling, tW, tH);
                //Load slide image
                var $newImg = $imgContainer.find('img').eq($img.data('index'));

                //image src from a tag
                $newImg.data('index',$img.data('index'))
                    .css({'display':'none','border':'none'})
                    .width('auto').height('auto');
                if ($img.data('link')) {
                    var $alink = $('<a>');
                    $alink.attr('href',$img.data('link'));
                    if ($img.data('target'))
                        $alink.attr('target',$img.data('target'));
                    $newImg.before($alink).appendTo($alink);
                }
                $newImg.imageLoadAndCall($img.parent().attr('href'),
                    function () {
                        prepare.createSlide($newImg);
                    }
                );
                //Last image
                if ($img.data('last')) prepare.showThumbnail();
            },
            //----- 2nd
            createSlide: function ($newImg) {
                prepare._scaleAndLayout($newImg, settings.scaling, pW, pH);
            },
            //----- 3rd
            showThumbnail: function () {
                timer = setInterval(prepare._thumbEvent, settings.thmDuration);
            },
            _thumbEvent: function () {
                var $img = $thmContainer.find('img').eq(currentIndex++);
                $img.fadeTo(settings.thmDuration,settings.thmDarkness);
                if ($img.data('last')) {
                    clearInterval(timer);
                    spinner.off();
                    effect.fadeIn(0);
                    currentIndex = 0;
                    prepare.complete();
                }
            },
            //----- Last
            complete: function () {
                $thmContainer.find('img').each( function (index) {
                    $(this).click( function () {
                        if (settings.interval > 0) clearInterval(timer);
                        effect.fadeOut(currentIndex);
                        currentIndex = $(this).data('index');
                        effect.fadeIn(currentIndex);
                        if (settings.interval > 0) 
                            timer = setInterval(prepare._autoplayEvent, 
                                settings.interval);
                        return false;
                    }).hover( function () {
                        $(this).stop(true,true)
                            .fadeTo(settings.thmDuration,1.0);
                    }, function () {
                        if ($(this).data('index') != currentIndex) 
                            $(this).stop(true,true)
                                .fadeTo(settings.thmDuration,settings.thmDarkness);
                    });
                });
                 
                if (settings.interval > 0) {
                    timer = setInterval(prepare._autoplayEvent, settings.interval);
                }
            },
            _autoplayEvent: function () {
                var $img = $thmContainer.find('img').eq(currentIndex);
                if ($img.data('index')==0 && $img.data('last')) {
                    settings.interval = 0;
                    clearInterval(timer);
                    return;
                }
                effect.fadeOut(currentIndex);
                if ($img.data('last')) currentIndex = 0;
                else currentIndex++;
                effect.fadeIn(currentIndex);
            }
        }
        //Effect
        var effect = {
            fadeIn: function (imgIndex) {
                var $thumbnail = $thmContainer.find('img').eq(imgIndex);
                if ($txtContainer) {
                    var text = $thumbnail.data('description');
                    if (!text) text = $thumbnail.parent().attr('title');
                    if (!text) text = "";
                    $txtContainer.html(text);
                }
                $thumbnail.fadeTo(0,1.0);
                $imgContainer.find('img').eq(imgIndex)
                    .stop(true,true).fadeIn(settings.duration);
            },
            fadeOut: function (imgIndex) {
                $thmContainer.find('img').eq(imgIndex)
                    .fadeTo(0,settings.thmDarkness);
                $imgContainer.find('img').eq(imgIndex)
                    .stop(true,true).fadeOut(settings.duration/3);//shorten
           }
        }
        var spinner = {
            on: function () {
                if (!settings.spinner) return;
                var $spn = $('<img>');
                $spn.addClass('spinner');
                $imgContainer.append($spn);
                $spn.imageLoadAndCall(settings.spinner,function () {
                    prepare._scaleAndLayout($spn, 'none', pW, pH);
                });
            },
            off: function () {
                if (!settings.spinner) return;
                var $spn = $imgContainer.find('img.spinner');
                $spn.fadeOut(settings.thmDuration);
            }
        }

        //Load data if json
        if  (settings.json) {
            var items = settings.json.items;
            for (var i = 0; i < items.length; i++) {
                var $li = $('<li>');
                var $a = $('<a>');
                var $img = $('<img>');
                $a.attr('href',items[i].url);
                $img.attr('src',items[i].thumb?items[i].thumb:items[i].url)
                    .data('fromJson',true);
                if (items[i].description)
                    $img.data('description',items[i].description);
                if (items[i].link)
                    $img.data('link',items[i].link);
                if (items[i].target)
                    $img.data('target',items[i].target);
                $(this).find('ul').append($li);
                $li.append($a);
                $a.append($img);
            }
        }
        
        //Initialize
        var timer;
        var currentIndex = 0;
        var $imgContainer = $(this).find('#'+settings.imageId);
        var $thmContainer = $(this).find('ul li');
        var $txtContainer;
        if (settings.textId)
            $txtContainer = $(this).find('#'+settings.textId);

        var pW = $imgContainer.width(), pH = $imgContainer.height(),
            tW = $thmContainer.width(), tH = $thmContainer.height();
        
        if ($imgContainer.css('position') === 'static')
            $imgContainer.css({'position':'relative'});
        if ($thmContainer.css('position') === 'static')
            $thmContainer.css({'position':'relative'});

        $thmContainer.find('img').last().data('last',true);
        $thmContainer.find('img').each( function (index) {
            var $img = $('<img />');
            $img.hide();
            $imgContainer.append($img);
            $(this).data('index',index)
                   .css({'display':'none','border':'none'})
                   .width('auto').height('auto');
        });
        spinner.on();
        $thmContainer.find('img').each(function (index) {
            $(this).imageLoadAndCall(null,
                function () {
                     prepare.createThumbnail($(this));
                }
            );
        });
    
        return this;
    }

}(jQuery));

