(function ($_) {
    function gid (id) {
        return document.getElementById(id);
    }
    function random (prefix) {
        return (prefix?prefix:"") + Math.random().toString(36).slice(2);
    }
    function Worker (_interval) {
        var self = {
            init: function () {
                return this;
            },
            regist: function (callback, bindObj) {
                this.tasks.push({
                    callback: callback,
                    bindObj: bindObj || this,
                    arguments: []
                });
                if ( this.task_id == null ) {
                    return this.start_worker();
                }
            },
            start_worker: function () {
                this.task_id = setInterval(function () {
                    if ( self.tasks.length && !self.lock ) {
                        self.lock = true;
                        var task = self.tasks.shift();
                        task.callback.apply(task.bindObj, task.arguments);
                        self.lock = false;
                    } else if ( self.tasks.length == 0 && self.lock ) {
                        clearInterval( self.task_id );
                        self.task_id = null;
                    } else {}
                }, this.interval);
            },
            setInterval: function (_interval) {
                this.interval = _interval;
            },
            tasks: [],
            task_id: null,
            lock: false,
            interval: _interval || 100
        };
        return self.init();
    };
    var worker = new Worker(100),
        loader = function (image, retry_count) {
            var retry = arguments.callee.caller,
                retry_count = retry_count || 0;
            worker.regist(function () {
                this.src     = this.getAttribute('rel');
                this.onerror = function () {
                    retry.count = !retry.count ? 1 : ++retry.count;
                    return retry.count <= retry_count ? retry.apply(image, [image, retry_count]) : ( image.onerror=function(){} );
                };
            }, image);
        },
        format = function (str, params) {
            var params = params || {};
            return ( str || "" ).replace(/(?:{([^}]+)})/g, function (a,vars) {
                return params[vars] ? params[vars] : "";
            });
        };
    $_.fn.extend({
        carouselSuperLite: function (_option) {
            var option = $_.extend({
                dataSource: "",
                params: {},
                image_width: 60,
                image_height: 60,
                count: 6,
                speed: 1000,
                easing: 'swing',
                position: function(){return true},
                format: '<a href="{link}" target="_blank"><img src="/img/noimage/s.gif" /></a>',
//                disableClass: 'disable',
                disableClassPrev: 'disable-prev',
                disableClassNext: 'disable-next',
                selectClass: 'selected',
                retry_count: 0,
                load_interval: 100,
                padding: 6
            }, _option), targets = this;
            return $_.post(option.dataSource, option.params, function (res, state) {
               if ( state == 'success' && res.is_success ) {
                   var images = $_.makeArray(res.data),
                   image_list_array = $_.map(images, function (image, i) {
                           // fixed position
                           $_.isFunction( option.position ) && option.position.call(null, image, i) && ( option.position = i );
                           // format list tag
                           return format('<li id="{list_id}">' + option.format + '</li>', $_.extend(image, option, {
                               list_id:random('_')
                           }));
                       });

                   if ( $_.browser.msie && $_.browser.version >= 8 ) {
                       var position    = $_.isFunction( option.position ) ? 0 : option.position,
                           count       = option.count > images.length ? images.length : option.count,
                           center      = Math.max( position - Math.floor(count/2), 0 ),
                           image_list  = image_list_array.slice(center, center+count).join(""),
                           images      = images.slice(center, center+count);
                       option.position = Math.max(position-center, 0);
                   } else {
                       var image_list = image_list_array.join("");
                   }

                   worker.setInterval(option.load_interval);
                   targets.each(function (target_count) {
                       var self        = this,
                           ulbox       = $_(option.ulbox,   this).append( image_list ),
                           prevBtn     = $_(option.prevBtn, this),
                           nextBtn     = $_(option.nextBtn, this),
                           max         = Math.max(images.length - option.count,0),
                           count       = option.count > images.length ? images.length : option.count,
                           box_width   = ( option.image_width * count ) + ( count * option.padding * 2 ),
                           position    = $_.isFunction( option.position ) ? 0 : option.position,
                           easing      = $_.easing.hasOwnProperty(option.easing) ? option.easing : 'swing',
                           retry_count = option.retry_count,
                           loaded      = {},
                           is_last     = false,
                           loadImage = function () {
                               $_.each(images.slice(position, position+count), function (i, image) {
                                   if ( !loaded.hasOwnProperty( image.list_id ) ) {
                                       try {
                                           var tag = gid( image.list_id ).getElementsByTagName('img')[0];
                                           loader(tag, retry_count);
                                       } catch (e) {}
                                       loaded[ image.list_id ] = true;
                                   }
                               });
                           },
                           scrollTo  = function (is_static) {
                               loadImage();
                               ulbox.animate({
                                   left: -( ( option.image_width * position ) + ( position * option.padding * 2 ) ) + "px"
                               }, is_static ? 0 : option.speed, easing, function () {
                                   if ( position + count >= max && !is_last ) {
                                       option.params.page += 1;
                                       $_.post(option.dataSource, option.params, function (_res, state) {
                                           eval('var res = ' + _res);
                                           if ( state == 'success' && res.is_success && res.data.length ) {
                                               var image_list = $_.map(res.data, function (image) {
                                                   images.push(image);
                                                   max++;
                                                   return format('<li id="{list_id}">' + option.format + '</li>', $_.extend(image, option, {
                                                       list_id:random('_')
                                                   }));
                                               }).join('');
                                               $_(option.ulbox, self).append( image_list );
                                               updateBtnState();
                                           } else {
                                               is_last = true;
                                               updateBtnState();
                                           }
                                       });
                                   } else {
                                       updateBtnState();
                                   }
                               });
                           },
                           scrollToCenter = function () {
                               $_.className.add(gid(images[ position ].list_id), option.selectClass);
                               position = Math.max( Math.min( position - Math.floor( count / 2 ), max ), 0 );
                               scrollTo(true);
                           },
                           updateBtnState = function () {
                               prevBtn[ ( position > 0   ? 'remove' : 'add' ) + 'Class' ]( option.disableClassPrev );
                               nextBtn[ ( position < max ? 'remove' : 'add' ) + 'Class' ]( option.disableClassNext );
//                               prevBtn[ ( position > 0   ? 'remove' : 'add' ) + 'Class' ]( option.disableClass );
//                               nextBtn[ ( position < max ? 'remove' : 'add' ) + 'Class' ]( option.disableClass );
                           };
                       /* set style sheet */
                       // $_( this ).css('width', box_width + 54), ulbox.parent().css('width', box_width), ulbox.css('height', option.image_height);
                       /* bind event listener */
                       prevBtn.bind('mousedown', function () {
                           position = Math.max(0, position - count);
                           scrollTo();
                       });
                       nextBtn.bind('mousedown', function () {
                           position = ( position + count ) > max ? max : ( position + count );
                           scrollTo();
                       });
                       /* initialize */
                       scrollToCenter();
                   });
               }
            }, 'json') && this;
        }
    });
})(jQuery);

