/*
    Common Grid 1.1.9
    
    Copyright (c) 2010 STRAIGHTLINE<http://www.straightline.jp/> All rights reserved.
*/

var AdjustGrid = new Class({
	Implements: [Options,Events],
    resizeTimer: null,
    isFirst: true,
    isAdjusting: false,
    animationType: {
        fade: 0,
        move: 1,
        fadeWrapper: 2
    },
    options: {
        ajaxLoaderSrc: 'ajax-loader.gif',
        ajaxLoaderTop: 20,
        ajaxLoaderLeft: 20,
        wrapperElementId: 'wrapper',
        wrapperMinWidth: 0,
        wrapperMaxWidth: 'auto',
        gridItemDelay: 50,
		onComplete: $empty,
		onAnimationComplete: $empty,
        loadAnimation: true,
        loadAnimationType: 1,
        resizeAnimation: true,
        resizeAnimationType: 1,
        fadeDuration: 500,
        fadeTransition: 'sine:in:out',
        moveDuration: 500,
        moveTransition: 'expo:in:out',
        isQueueJumping: false
    },
    
    initialize: function(options) {
        this.setOptions(options);

        window.addEvent('load', function() {
            this.readjust.run([
                this.options.loadAnimation, 
                this.options.loadAnimationType
            ], this);
        }.bind(this));
        
        var ajaxLoader = new Element('div', {
            id: 'ajax-loader',
            styles: {
                position: 'fixed',
                top: this.options.ajaxLoaderTop,
                left: this.options.ajaxLoaderLeft,
                'z-index': 999999
            }
        });
        var ajaxLoaderImage = new Element('img', {
            src: this.options.ajaxLoaderSrc
        });
        ajaxLoader.adopt(ajaxLoaderImage);
        $(document.body).adopt(ajaxLoader);
        
        window.addEvent('resize', function() {
            $clear(this.resizeTimer);
            this.resizeTimer = (function() {
                if (this.isAdjusting == false) {
                    this.readjust.run([
                        this.options.resizeAnimation,
                        this.options.resizeAnimationType
                    ], this);
                }
            }.bind(this)).delay(200);
        }.bind(this));
    },
    
    readjust: function(isAnimation, animationType) {
        var timer = (function() {
            if (this.isFirst == false) {
                $clear(timer);
                this.adjust.run([isAnimation, animationType], this);
            }
        }.bind(this)).periodical(50);
    },
    
    adjust: function(isAnimation, animationType) {
        this.isAdjusting = true;
        
        var wrapperMinWidth = this.options.wrapperMinWidth;
        var wrapper = $(this.options.wrapperElementId);
        
        wrapper.setStyle('position', 'relative');
        var windowWidth = window.getWidth();
        var curWrapperWidth = wrapper.getSize().x;
        
        if (wrapper.retrieve('curWindowWidth') != windowWidth) {
            wrapper.store('curWindowWidth', windowWidth);
            if (windowWidth > this.options.wrapperMaxWidth) {
                wrapper.setStyle('width', this.options.wrapperMaxWidth);
            } else if (windowWidth < this.options.wrapperMinWidth) {
                wrapper.setStyle('width', this.options.wrapperMinWidth);
            } else {
                wrapper.setStyle('width', 'auto');
            }
        }


        var grids = $$('.grid');
        var isLoopBack = false;
        for (var gridIndex = 0; gridIndex < grids.length; gridIndex++) {
            var grid = grids[gridIndex];
            
            if (grid.retrieve('fixed')) {
                continue;
            }
            var isContinue = false;
            var childGrids = grid.getElements('.grid');
            childGrids.each(function(childGrid) {
                if ($defined(childGrid.retrieve('fixed')) == false) {
                    isContinue = true;
                }
            });
            if (isContinue) {
                continue;
            }
            var parentGrid = grid.getParent('.grid');
            if ($defined(parentGrid) && $defined(parentGrid.retrieve('fixed')) == false) {
                isLoopBack = true;
            }
            grid.setStyle('position', 'relative');
            
            var gridItems = grid.getElements('.grid-item');
            var gridWidth = grid.getSize().x;
            var sheet = new Array();
            var row = 0;
            var col = 0;
            var curUpperCol = 0;
            var gridMaxHeight = 0;
            for (var gridItemIndex = 0; gridItemIndex < gridItems.length; gridItemIndex++) {
                //alert("Num: " + gridItemIndex + ", Row: " + row + ", Col:" + col);
                var gridItem = gridItems[gridItemIndex];
                if (grid != gridItem.getParent('.grid')) {
                    continue;
                }
                
                var gridItemWidth = gridItem.getComputedSize().totalWidth;
                gridItem.removeClass('grid-item-first');
                gridItem.removeClass('grid-item-last');
                gridItem.removeClass('col-first');
                gridItem.removeClass('col-last');
                gridItem.removeClass('row-last');
                gridItem.eliminate('fixed', false);
                gridItem.setStyle('position', 'absolute');
                gridItem.store('positionLeft', col > 0 ? sheet[row][col - 1].retrieve('positionRight') : 0);
                gridItem.store('positionRight', col > 0 ? gridItem.retrieve('positionLeft') + gridItemWidth : gridItemWidth);
                
                if (gridItemIndex + 1 == gridItems.length) {
                    gridItem.addClass('grid-item-last');
                    gridItem.addClass('col-last');
                }
                if (row == 0 && col == 0) {
                    gridItem.addClass('grid-item-first');
                    gridItem.addClass('col-first');
                } else if (col == 0) {
                    gridItem.addClass('col-first');
                } else if (gridItem.retrieve('positionRight') > gridWidth) {
                    sheet[row][col - 1].addClass('col-last');
                    col = 0;
                    row++;
                    curUpperCol = 0;
                    gridItemIndex--;
                    continue;
                }
                
                var gridItemHeight = gridItem.getComputedSize().totalHeight;
                if (row == 0) {
                    if (col == 0) {
                        gridItem.store('positionTop', 0);
                        gridItem.store('positionBottom', gridItemHeight);
                    } else {
                        gridItem.store('positionTop', sheet[row][col - 1].retrieve('positionTop'));
                        gridItem.store('positionBottom', gridItem.retrieve('positionTop') + gridItemHeight);
                    }
                } else {
                    var left = gridItem.retrieve('positionLeft');
                    var right = gridItem.retrieve('positionRight');
                    var height = gridItemHeight;
                    
                    var upperGridItem = null;
                    var isSkip = false;
                    for (var upperCol = curUpperCol; upperCol < sheet[row - 1].length; upperCol++) {
                        var curUpperGridItem = sheet[row - 1][upperCol];
                        var upperLeft = curUpperGridItem.retrieve('positionLeft');
                        var upperRight = curUpperGridItem.retrieve('positionRight');
                        
                        if (this.options.isQueueJumping && $defined(upperGridItem) == false) {
                            var curUpperGridItemBottom = curUpperGridItem.retrieve('positionBottom');
                            var heightRange = 0;
                            if (upperCol + 1 != sheet[row - 1].length) {
                                heightRange = curUpperGridItemBottom - sheet[row - 1][upperCol + 1].retrieve('positionBottom');
                            } else if (sheet[row - 1].length > 1) {
                                heightRange = curUpperGridItemBottom - sheet[row - 1][upperCol - 1].retrieve('positionBottom');
                            }
                            
                            if (
                                heightRange > 0 && 
                                height / 2 <= heightRange
                            ) {
                                var isException = false;
                                if (
                                    col > 0 &&
                                    curUpperGridItemBottom + height <= sheet[row][col - 1].retrieve('positionBottom') + sheet[row][col - 1].getComputedSize().totalHeight / 2
                                ) {
                                    isException = true;
                                }
                                if (isException == false) {
                                    gridItem = curUpperGridItem;
                                    gridItemIndex--;
                                    isSkip = true;
                                    curUpperCol = upperCol + 1;
                                    break;
                                }
                            }
                        }
                        
                        // Š®‘Sˆê’v
                        if (upperLeft == left && right == upperRight) {
                            upperGridItem = curUpperGridItem;
                            curUpperCol = upperCol + 1;
                            break;
                        } else if (
                            // Š®‘S“à•ï
                            (upperLeft <= left && right <= upperRight) ||
                            (upperLeft >= left && right >= upperRight) ||
                            // •”•ª“à•ï
                            (upperLeft < left && left < upperRight) ||
                            (upperLeft < right && right < upperRight)
                        ) {
                            if (
                                $defined(upperGridItem) == false ||
                                curUpperGridItem.retrieve('positionBottom') > upperGridItem.retrieve('positionBottom')
                            ) {
                                upperGridItem = curUpperGridItem;
                                if (right >= upperRight) {
                                    curUpperCol = upperCol + 1;
                                }
                            }
                        }
                    }

                    if (isSkip == false) {
                        gridItem.store('positionTop', $defined(upperGridItem) ? upperGridItem.retrieve('positionBottom') : sheet[row][col - 1].retrieve('positionTop'));
                        gridItem.store('positionBottom', $defined(upperGridItem) ? upperGridItem.retrieve('positionBottom') + height : sheet[row][col - 1].retrieve('positionTop') + height);
                    }
                }
                
                gridMaxHeight = Math.max(gridItem.retrieve('positionBottom'), gridMaxHeight);
                wrapperMinWidth = Math.max(gridItem.retrieve('positionRight'), wrapperMinWidth);
                
                if (!sheet[row]) {
                    sheet[row] = new Array();
                }
                if (!sheet[row][col]) {
                    sheet[row][col] = new Array();
                }
                sheet[row][col] = gridItem;
                col++;
                
                gridItem.store('fixed', true);
            }
            
            if ($defined(sheet[row])) {
                var lastRowPositionRight = 0;
                sheet[row].each(function(lastRowGridItem, lastIndex) {
                    lastRowGridItem.addClass('row-last');
                    if (sheet[row].length == lastIndex + 1) {
                        lastRowPositionRight = lastRowGridItem.retrieve('positionRight');
                    }
                });
                if (row > 0) {
                    sheet[row - 1].each(function(lastRowGridItem, lastIndex) {
                        if (lastRowGridItem.retrieve('positionLeft') >= lastRowPositionRight) {
                            lastRowGridItem.addClass('row-last');
                        }
                    });
                    
                }
            }
            
            grid.setStyle('height', gridMaxHeight);
            grid.store('fixed', true);
            if (isLoopBack) {
                gridIndex = -1;
            }
        }
        
        grids.each(function(grid) {
            grid.eliminate('fixed');
        });
        wrapper.setStyle('width', curWrapperWidth);
        
        var index = 0;
        var gridItems = $$('.grid-item');
        var chain = new Chain();
        var duration;
        var transition;
        chain.chain(
            function() {
                wrapper.setStyle('width', Math.min(wrapperMinWidth, this.options.wrapperMaxWidth == 'auto' ? wrapperMinWidth : this.options.wrapperMaxWidth));
                if (isAnimation && animationType != this.animationType.fadeWrapper) {
                    wrapper.setStyle('opacity', 1);
                }
                $('ajax-loader').tween('opacity', 0);
            }.bind(this)
        );
        
        if (isAnimation) {
            if (
                $defined(animationType) == false || 
                animationType == this.animationType.fade ||
                animationType == this.animationType.fadeWrapper
            ) {
                duration = this.options.fadeDuration;
                transition = this.options.fadeTransition;
            } else if (animationType == this.animationType.move) {
                duration = this.options.moveDuration;
                transition = this.options.moveTransition;
            }
        }
        gridItems.each(function(gridItem, index) {
            if (isAnimation && animationType != this.animationType.fadeWrapper) {
                if (
                    this.isFirst ||
                    gridItem.getStyle('top').toInt() != gridItem.retrieve('positionTop') ||
                    gridItem.getStyle('left').toInt() != gridItem.retrieve('positionLeft')
                ) {
                    var properties;
                    if (
                        $defined(animationType) == false || 
                        animationType == this.animationType.fade
                    ) {
                        gridItem.setStyles({
                            top: gridItem.retrieve('positionTop'),
                            left: gridItem.retrieve('positionLeft'),
                            opacity: 0
                        });
                        properties = {
                            opacity: 1
                        };
                    } else if (animationType == this.animationType.move) {
                        properties = {
                            top: gridItem.retrieve('positionTop'),
                            left: gridItem.retrieve('positionLeft')
                        };
                    }
                    if (index + 1 == gridItems.length) {
                        chain.chain(
                            function() { 
                                gridItem.get('morph', {
                                    duration: duration,
                                    transition: transition,
                                    link: 'chain',
                                    onComplete: function() {
                                        this.fireEvent('animationComplete');
                                        this.isFirst = false;
                                    }.bind(this)
                                }).start(properties);
                            }.bind(this)
                        );
                    } else {
                        chain.chain(
                            function() { 
                                gridItem.get('morph', {
                                    duration: duration,
                                    transition: transition,
                                    link: 'chain'
                                }).start(properties);
                            }.bind(this)
                        );
                    }
                    index++;
                }
            } else {
                gridItem.setStyles({
                    top: gridItem.retrieve('positionTop'),
                    left: gridItem.retrieve('positionLeft')
                });
            }
            
        }.bind(this));
        
        if (isAnimation && animationType == this.animationType.fadeWrapper) {
            chain.chain(
                function() {
                    wrapper.get('tween', {
                        property: 'opacity',
                        duration: duration,
                        transition: transition,
                        link: 'chain',
                        onComplete: function() {
                            this.fireEvent('animationComplete');
                            this.isFirst = false;
                        }.bind(this)
                    }).start(1);
                }.bind(this)
            );
        }

        this.fireEvent('complete');
        
        var runChain = function() {
    		if (chain.callChain() == false) {
                runChain = $clear(timer);
                
                this.isAdjusting = false;
                
                if (isAnimation == false) {
                    wrapper.setStyle('opacity', 1);
                    this.isFirst = false;
                    this.fireEvent('animationComplete');
                }
            } 
    	}.bind(this);
    	var timer = runChain.periodical(this.options.gridItemDelay);
    }
    
});

