// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.

define(['jquery'], function() {
    (function($) {
        // jQuery plugin definition
        $.fn.hpPanels = function(options) {
          
            var instance;

            function hpPanels(elem) {
              
                var container;
                var gutter = 10;
                var resizeTimeout;
                
                // lays out the next row of panels
                function nextRow(layoutData) {
                    var usedRowWidth = 0;
                    var usedRowHeight = 0;
                    var index = layoutData.nextIndex;
                    var panel;
                    var lastRowIndex;
                    var extraWidth;
                    var extraPanelWidth;
                    var left;
                    var newPanelWidth;
                    var css;
                    
                    // determine which panels we can fit in this row and how much space that will use
                    while (index < layoutData.panels.length) {
                        panel = layoutData.panels[index];
                        
                        // can we fit another panel?
                        if ((usedRowWidth + $(panel).data('baseWidth')) > layoutData.containerWidth) {
                            // can't fit any more
                            
                            // if we didn't even fit one panel, adjust to at least use it
                            if (usedRowWidth === 0) {
                                usedRowWidth = $(panel).data('baseWidth') + gutter;
                                usedRowHeight = $(panel).data('baseHeight');
                            }
                            
                            break;
                        }
                        
                        // account for usage
                        usedRowWidth += $(panel).data('baseWidth') + gutter;
                        usedRowHeight = Math.max(usedRowHeight, $(panel).data('baseHeight'));
                        index += 1;
                    }
                    // only need n-1 gutters
                    usedRowWidth -= gutter;
                    
                    lastRowIndex = (index === layoutData.nextIndex ? index : index - 1);
                    extraWidth = (layoutData.containerWidth - usedRowWidth);
                    extraPanelWidth = (extraWidth / (lastRowIndex - layoutData.nextIndex + 1));
                    left = 0;
                    
                    //console.log(layoutData.nextIndex + '-' + lastRowIndex + " container: " + layoutData.containerWidth +
                    //            'x' + layoutData.containerHeight + " start: " + layoutData.top + " used: " + usedRowWidth +
                    //            'x' + usedRowHeight + " extra: " + extraWidth + " panelExtra: " + extraPanelWidth);
                    
                    // position panels in this row
                    index = layoutData.nextIndex;
                    while (index <= lastRowIndex) {
                        panel = layoutData.panels[index];
                        
                        panel.style.position = 'absolute';
                        // give panel its proportion of the extra width
                        newPanelWidth = $(panel).data('baseWidth') + extraPanelWidth;
                        css = {
                          left: left + 'px',
                          top: layoutData.top + 'px',
                          width: newPanelWidth,
                          // give all panels in the same row the same height
                          height: usedRowHeight
                        };
                        $(panel).animate(css);
                        
                        left += newPanelWidth + gutter;
                        index += 1;
                    }
                    // only need n-1 gutters
                    left -= gutter;
                    
                    // adjust layout data for start of next row
                    layoutData.nextIndex = index;
                    layoutData.top += usedRowHeight + gutter;
                }

                function layout(elem) {
                    elem.style.height = '';
                    // the layoutData tracks where we are in the process as we layout each row
                    var layoutData = {
                        top: 0,
                        containerWidth: $(elem).width(),
                        containerHeight: $(elem).height(), 
                        panels: $('> li', elem),
                        nextIndex: 0
                    };
                    
                    while (layoutData.nextIndex < layoutData.panels.length) {
                        nextRow(layoutData);
                    }
                    
                    // set the container to height to contain all rows
                    $(container).height(layoutData.top);
                }

                this.initialize = function(elem) {
                    container = elem;
                    
                    if ($('body').hasClass('style6')) {
                        gutter = 0;
                    }
                    
                    // save each panel's original width and height as a reference
                    $('> li', elem).each(function(index, panel) {
                        $(panel).data('baseWidth', $(panel).width());
                        $(panel).data('baseHeight', $(panel).height());
                    });
                    
                    layout(elem);
                    
                    $(window).resize(function() {
                        // delay layout to be less jumpy
                        if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
                        resizeTimeout = setTimeout(function() {
                          layout(elem);
                        }, 100);
                    });
                };
                
                this.reset = function() {
                    layout(container);
                };
            }
            
            if ( typeof options === 'string' ) { 
                // call method
                var args = Array.prototype.slice.call( arguments, 1 );

                this.each(function() {
                    instance = $.data( this, 'hpPanels' );
                    if ( !instance ) {
                        if (window.console) {
                            window.console.error(
                                "cannot call methods on hpPanels prior to initialization; " +
                                "attempted to call method '" + options + "'" );
                        }
                        return;
                    }
                    if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
                        if (window.console) {
                            window.console.error(
                                "no such method '" + options + "' for hpPanels instance" );
                        }
                        return;
                    }
                    // apply method
                    instance[ options ].apply( instance, args );
                });  
            } else {
                // pluginify
                var ret;
                this.each(function() {
                    var $elem = $(this);
                    instance = new hpPanels($elem[0]);
                    $.data(this, 'hpPanels', instance);
                    instance.initialize($elem[0]);
                    ret = ret ? ret.add($elem) : $elem;
                });
                return ret;
            }
        };
    }(jQuery));
});
