/*
File:           slidegrid.js
Description:    for more information see http://www.zackgrossbart.com/hackito/slidegrid/

*******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/
 
 
 function random( min, max) {
	if( min > max ) 
	{
		return( -1 );
	}
	if( min == max ) 
	{
		return( min );
	}
 
    return( min + parseInt( Math.random() * ( max-min+1)));
}

 function setEmpty(/*array*/emptyCells, /*int*/ i_col, /*int*/ i_row, /*int*/ i_x, /*int*/ i_y)
 {
		var index = emptyCells.length;
		emptyCells[index] = { col: i_col, row: i_row, x: i_x, y: i_y};
 }
 
 function getEmpty(/*array*/emptyCells)
 {
 		if(emptyCells.length <= 0)
		{
			return null;
		}
		
		var emptyCell = emptyCells[0];
		
		emptyCells.splice(0,1);
		return emptyCell;
 }
 
/**
 * Adds a specific cell to the set of used cells.  Used cells are skipped 
 * when laying cells out in the future.
 * 
 * @param usedCells the array of used cells
 * @param col       the column of the used cell
 * @param row       the row of the used cell
 */
function setUsed(/*array*/ usedCells, /*int*/col, /*int*/row) {
    var index = usedCells.length;
    usedCells[index] = { left: col, top: row};
}

/**
 * Lets you know if a specific column and row index has already been used.
 * 
 * @param usedCells the array of used cells
 * @param col       the column of the cell to check
 * @param row       the row of the cell to check
 */
function isUsed(/*array*/ usedCells, /*int*/ col, /*int*/ row) {
    for (var i = 0; i < usedCells.length; i++) {
        if (usedCells[i].left === col &&
            usedCells[i].top === row) {
            return true;
        }
    }
    return false;
}

/**
 * Applies the styling to a specific cell.
 * 
 * @param cell       The JQuery object representing the cell to style
 * @param x          the left position of the cell in EMs
 * @param y          the top position of the cell in EMs
 * @param cellWidth  the width of the cell in EMs
 * @param cellHeight the height of the cell in EMs
 * @param animate    true if this style should be animated and false otherwise
 */
function styleCell(cell, x, y, cellWidth, cellHeight, /*boolean*/animate) {
    if (animate) {
        cell.animate({ 
            left: x + "px",
            top: y + "px"
            }, 1000, "swing" );
    } else {
        cell.css({
            width: cellWidth + "px",
            height: cellHeight + "px",
            position: "absolute",
			margin: "0px",
            left: x + "px",
            top: y + "px"
        });
    }
}


/**
 * This is a kind of hacky function to figure out the pixel size of a single
 * EM in the current container.  I wish there was a better way to handle this, 
 * but I haven't found it yet.
 * 
 * @param el     the parent element of the grid
 */
function getComputedEm(el) {
    el.append("<div id=\"emtestdiv\"></div>");
    var testel = $("#emtestdiv");
    testel.css({
        height: "1em",
        position: "absolute",
        backgroundColor: "#f00"
    });
    
    var emValue = testel.height();
    testel.remove();
    return emValue;
}
 
var hasDrawn = false;

/**
 * Aligns a set of elements in a resizable grid.
 * 
 * @param cellWidth  the width of each cell in EMs
 * @param cellHeight the height of each cell in EMs
 * @param padding    the paddin between each cell in EMs
 */
function alignGrid(/*int*/ cellWidth, /*int*/ cellHeight, /*int*/ padding) {
    var x = 0;
    var y = 0;
    var count = 1;
    var curCol = 0;
    var curRow = 0;
    var usedCells = [];
	var emptyCells = [];
	var contentHeight = (cellHeight + padding);
	
    $(".slidegrid").each(function() 
	{
        var cols = Math.floor(($(window).width() - 220) / ((cellWidth + padding)));   
        $(this).css("position", "relative");
        var children = $(this).children("div");
		
        for (var i = 0; i < children.length; i++) 
		{
            
            if(isUsed(usedCells, curCol, curRow)) 
			{
                i--;
            }
			else 
			{
				
                if(children.eq(i).hasClass("widecell")) 
				{
					
					if (isUsed(usedCells, curCol + 1, curRow) || ((curCol + 1 >= cols) && (cols >= 2))) 
					{
						i--;
						setEmpty(emptyCells, curCol, curRow, x, y);
					}
					else 
					{
						styleCell(children.eq(i), x, y, (cellWidth * 2) + padding, (cellHeight), hasDrawn);
						setUsed(usedCells, curCol, curRow);
						setUsed(usedCells, curCol + 1, curRow);
					}
                } 
				
				else if(children.eq(i).hasClass("bigcell"))
				{
					if(isUsed(usedCells, curCol, curRow + 1) || isUsed(usedCells, curCol + 1, curRow + 1) || isUsed(usedCells, curCol + 1, curRow) || ((curCol + 1 >= cols) && (cols >= 2))) 
					{
						i--;
						setEmpty(emptyCells, curCol, curRow, x, y);
					}
					else 
					{
						styleCell(children.eq(i), x, y, (cellWidth * 2) + padding, (cellHeight * 2) + padding, hasDrawn);
						setUsed(usedCells, curCol, curRow);
						setUsed(usedCells, curCol, curRow + 1);
						setUsed(usedCells, curCol + 1, curRow + 1);
						setUsed(usedCells, curCol + 1, curRow);
					}
					contentHeight += cellHeight + padding;
				}
				
				else if(children.eq(i).hasClass("highcell"))
				{
					if(isUsed(usedCells, curCol, curRow + 1))
					{
						i--;
						setEmpty(emptyCells, curCol, curRow, x, y);
					}
					else 
					{
						styleCell(children.eq(i), x, y, cellWidth, (cellHeight * 2) + padding, hasDrawn);
						setUsed(usedCells, curCol, curRow);
						setUsed(usedCells, curCol, curRow + 1);
						
					}
					contentHeight += cellHeight + padding;
				}
				else
				{
					var emptyCell = getEmpty(emptyCells);
					if(emptyCell != null)
					{
						styleCell(children.eq(i), emptyCell.x, emptyCell.y, cellWidth, cellHeight, hasDrawn);
						continue;
					}
					else
					{
						styleCell(children.eq(i), x, y, cellWidth, cellHeight, hasDrawn);
					}
                }
            }
            
            if ((count % cols) === 0) 
			{
                curCol = 0;
                curRow++;
                x = 0;
                y += cellHeight + padding;
				//$(this).css("height", y + cellHeight + padding + 40 +  "px");
				
				if(i != children.length-1)
					contentHeight = (curRow + 1) * (cellHeight + padding);
				//alert('row' + contentHeight);
				
            } 
			else 
			{
                x += cellWidth + padding;
                curCol++;
            }
            
            count++;
        }
        
        x = 0;
        y = 0;
        count = 1;
    });
    
	if (hasDrawn) {
		$("#content").animate({
			"height": contentHeight + "px"}, 1000, "swing" );
	} else {
		$("#content").css("height", contentHeight + "px");
	}
	
    hasDrawn = true;
}

var windowWidth = 0;

$(document).ready(function() 
{
    alignGrid(180, 180, 30);
    function resizeWindow(e) {
        if (windowWidth != $(window).width()) 
		{
            alignGrid(180, 180, 30);
            windowWidth = $(window).width();
        }
    }
    $(window).bind("resize", resizeWindow);
	
	$('#realign').click(function() {
		$('#slidegrid div:first').appendTo('#slidegrid');
		alignGrid(180, 180, 30);
	});
});

