(function () {

var DEFAULT_OPTIONS = {
    referenceSelector : '*',
    marginX           : 0,
    marginY           : 0,
    zoomable          : false,
    gaTracking        : true,
    preload           : false,
    zoom_image        : false
};

var AutoUpdatingMultiSizeImage = new Class({
    Implements: [Events, Class.Occlude],
    
    property: 'multisizeimage',
    
    initialize: function (element) {
        this.element = element;
        
        if (this.occlude()) {
            return this.occluded.occludedInitialize(element);
        }
        
        return this.occludedInitialize(element);
    },
    
    occludedInitialize: function () {
        var options;
        
        this.options = Object.clone(DEFAULT_OPTIONS);
        
        if (this.element.get('multisizeimageoptions')) {
            options = JSON.decode('{' + this.element.get('multisizeimageoptions') + '}');
            
            Object.append(this.options, options);
        }
        
        if (!this.options.marginX) {
            this.options.marginX = 0;
        }
        
        if (!this.options.marginY) {
            this.options.marginY = 0;
        }
        
        if (this.options.preload) {
            this.preload_mode = true;
        }
        else {
            this.preload_mode = false;
        }
        
        this.sizes = this.element.get('sizes').split(';').map(function (item, index) {
            return {
                x : parseInt(item.split(',')[0], 10),
                y : parseInt(item.split(',')[1], 10)
            }
        });
        
        this._resizeHandler = function (e) {
            this.onWindowResize.bind(this, e)();
        }.bind(this);
        
        //window.addEvent('resize', this._resizeHandler);
        
        if (window.eventHandler === undefined){
            window.addEvent('resizeHandlerInitialized', function(){
                window.eventHandler.add('resize', 'multisize-image', this._resizeHandler);
            });
        } else {
            window.eventHandler.add('resize', 'multisize-image', this._resizeHandler);
        }
        
        this._clickHandler = function (e) {
            this.onClick.bind(this, e)();
        }.bind(this);
        
        if(this.options.zoom_image == true){
            this.element.getParent().addEvent('click', this._clickHandler);
        }
        
        this.element.addEvent('click', this._clickHandler);
        
        //this._update_periodical = this.periodicalUpdate.periodical(250, this);
        
        this.updateSize();
        
        return this;
    },
    
    displayFull: function () {
        if (this.preload_mode) {
            this.preload_mode = false;
            this._preload_mode_deactivated = true;
            this.updateSize();
        }
        else {
            this.updateSize();
        }
    },
    
    onWindowResize: function (event) {
        if (!this.element.getParent()) {
            window.removeEvent('resize', this._resize_handler);
            return;
        }
        
        this.updateSize();
    },
    
    onClick: function (event) {
        var largest_fit, img_element;
        
        if (this.options.zoomable) {
            event.stop();
            
            largest_fit = this.getLargestFit(window.getSize());
            
            (function () {
                new StickyWin.Modal({
                    'content'         : '<img class="closeSticky" style="width: ' + largest_fit.x + 'px; height: ' + largest_fit.y + 'px;" src="' + this.element.get('image_url') + '/largest_fit?max_width=' + largest_fit.x + '&max_height=' + largest_fit.y + '"/>',
                    'className'       : 'modal_image',
                    'destroyOnClose'  : true,
                    'closeOnClickOut' : true,
                    'closeOnEsc'      : true,
                    'allowMultiple'   : false,
                    'maskOptions': {
                        'destroyOnHide' : true,
                        'style': {
                            'background-color' : 'black',
                            'opacity'  : .8,
                            'z-index'  : 9000,
                            'position' : 'absolute'
                        }
                    },
                    'onDestroy' : function () {
                        // Force unload of images on mobile webkit
                        this.element.getElements('img').each(function (image_element) {
                            image_element.set('src', resource_path + '/images/transparent.png');
                        }.bind(this));
                    }
                });
            }).delay(1, this); // Needed to prevent infinite recursion errors on iPad
           
            if (this.options.gaTracking && window.pageTracker) {
                pageTracker._trackEvent('multisizeimage', 'zoom', this.element.get('image_url'));
            }
        }
    },
    
    //periodicalUpdate: function () {
    //    if (this._reference_element_size !== JSON.encode(this.element.getParents(this.options.referenceSelector)[0].getSize())) {
    //        this.updateSize();
    //    }
    //},
    
    getLargestFit: function (max_size) {
        var reference_element, reference_element_size, max_width, max_height, best_size, smallest_size, curr_width, curr_height, curr_smallest;
        
        if (!max_size) {
            reference_element = this.element.getParents(this.options.referenceSelector)[0];
            
            reference_element_size = reference_element.getSize();
            
            if (this.options.ignoreWidth) {
                reference_element_size.x = null;
            }
            
            if (this.options.ignoreHeight) {
                reference_element_size.y = null;
            }
            
            /* Algorithm converted from python MultiSizeImage LargestFit view, keep in sync */
            
            if (reference_element_size.x) {
                max_width = reference_element_size.x - this.options.marginX;
            }
            else {
                max_width = null;
            }
            
            if (reference_element_size.y) {
                max_height = reference_element_size.y - this.options.marginY;
            }
            else {
                max_height = null;
            }
        }
        else {
            max_width  = max_size.x;
            max_height = max_size.y;
        }
        
        best_size     = null;
        smallest_size = null;
        curr_width    = 0;
        curr_height   = 0;
        curr_smallest = 0;
        
        this.sizes.each(function (size) {
            var tmp_w, tmp_h;
            
            tmp_w = size.x;
            tmp_h = size.y;
            
            if ((curr_width < tmp_w) && ((max_width === null) || (tmp_w <= max_width)) && (curr_height < tmp_h) && ((max_height === null) || (tmp_h <= max_height))) {
                best_size   = size;
                curr_width  = tmp_w;
                curr_height = tmp_h;
            }
            
            if ((smallest_size === null) || (tmp_w < curr_smallest)) {
                smallest_size = size;
                curr_smallest = tmp_w;
            }
        }.bind(this));
        
        if (best_size === null) {
            best_size = smallest_size;
        }
        
        return best_size;
    },
    
    updateSize: function () {
        var current_image_size, reference_element_size, image_src_uri, largest_fit_size, data, center_reference_element;
        
        if (this.options.frozen) return;
        
        current_image_size     = this.element.getSize();
        reference_element_size = this.element.getParents(this.options.referenceSelector)[0].getSize();
        largest_fit_size       = this.getLargestFit();
        
        this._reference_element_size = JSON.encode(reference_element_size);
        
        if ((largest_fit_size != current_image_size) || this._preload_mode_deactivated) {
            this._preload_mode_deactivated = false;
            
            image_src_uri = new URI(this.element.get('image_url') + '/largest_fit');
            
            if (this.preload_mode) {
                data = {
                    max_width  : 0,
                    max_height : 0
                };
            }
            else {
                data = {
                    max_width  : reference_element_size.x - this.options.marginX,
                    max_height : reference_element_size.y - this.options.marginY
                };
                
                if (this.options.ignoreWidth) {
                    data.max_width = undefined;
                }
                
                if (this.options.ignoreHeight) {
                    data.max_height = undefined;
                }
            }
            
            image_src_uri.setData(data);
            
            if (this.element.get('src') !== image_src_uri.toString()) { // for Opera
                this.element.set('src', image_src_uri.toString());
            }
            
            
            var old_size = this.element.getSize();
            
            this.element.setStyles({
                'width'  : largest_fit_size.x,
                'height' : largest_fit_size.y
            });
            
            if (this.options.centerWrapperParentSelector) {
                if (this.options.centerReferenceParentSelector) {
                    center_reference_element = this.element.getParents(this.options.centerReferenceParentSelector)[0];
                    //bss special
                    if (this.options.centerWrapperParentSelectorExtraWidth) {
                        center_wrapper_parent_selector_extra_width = this.options.centerWrapperParentSelectorExtraWidth;
                    }
                    else{
                        center_wrapper_parent_selector_extra_width = 0;
                    }
                    
                    this.element.getParents(this.options.centerWrapperParentSelector)[0].setStyles({
                        'width'  : center_reference_element.getSize().x + center_wrapper_parent_selector_extra_width,
                        'height' : center_reference_element.getSize().y
                    });
                }
                else {
                    this.element.getParents(this.options.centerWrapperParentSelector)[0].setStyles({
                        'width'  : largest_fit_size.x,
                        'height' : largest_fit_size.y
                    });
                }
            
                
                this.fireEvent('multisizeimagesizechanged', [largest_fit_size, old_size]);
                
                this.element.getParents('.iscroll_content').each(function (iscroll_content_element) {
                    var iscroll = iscroll_content_element.retrieve('iscroll');
                    
                    if (iscroll) {
                        (function () {
                            iscroll.refresh();
                        }.bind(this)).delay(1);
                    }
                }.bind(this));
            }
        }
    }
});

function activate_multisizeimages(element) {
    element.getElements('img.multisizeimage').each(function (multisizeimage_element) {
        var tmp = new AutoUpdatingMultiSizeImage(multisizeimage_element);
    });
}

window.element_activators.push(activate_multisizeimages);

window.AutoUpdatingMultiSizeImage = AutoUpdatingMultiSizeImage;

})();
