/**
 * @author Sjors
 */
var GridManager = new Class({
  Implements: [Options],
  options: {
    minRowWidth: 4,
    maxRowWidth: 6,
    openCardWidth: 3,
    margin: 20
  },
  cards: new Array(),

  openCard: '',

  initialize: function (container, options) {
    this.setOptions(options);
    this.container = document.id(container);

    if (this.options.minRowWidth < this.options.openCardWidth) {
      throw new Error('GridManager:initialize - minimal row width cannot be smaller than open card width');
    }
  },

  distribute: function () {
    if (this.cards.length == 0) {
      Denham.showNoCardsMessage();
      return;
    }

    Denham.hideNoCardsMessage();

    // Determine the amount of cards to place in a row
    var rowWidth;
    rowWidth = Math.floor((document.getSize().x + this.options.margin - 40) / (this.options.closedOuterWidth + this.options.margin));
    rowWidth = rowWidth < this.options.minRowWidth ? this.options.minRowWidth : rowWidth;
    rowWidth = rowWidth > this.options.maxRowWidth ? this.options.maxRowWidth : rowWidth;

    var amountCards = this.cards.length;

    if (this.openCard != '') {
      this.container.addClass('detailview');

      // Walk through the cards in the card collection, find the open card and determine its index in the current sorting
      var openCardIndex;
      for (var i=0; i<amountCards; i++) {
        if (this.cards[i].id == this.openCard) {
          openCardIndex = i;
          break;
        }
      }

      // Determine the row and the position in the row for the open card
      var openCardRow, openCardPosition;
      openCardRow      = Math.ceil((openCardIndex + 1) / rowWidth);
      openCardPosition = (openCardIndex + 1)%rowWidth;
      openCardPosition = openCardPosition == 0 ? rowWidth : openCardPosition;

      // Determine the space on either side of the card
      var spaceLeft, spaceRight;
      spaceLeft  = openCardPosition - 1;
      spaceRight = rowWidth - openCardPosition;

      // Determine which way to fold open
      var openPositionIndex;
      if (spaceLeft > spaceRight) {
				if (spaceLeft >= this.options.openCardWidth - 1) { //check if there is enough space to fit to the left
					openPositionIndex = (openCardPosition - 1) - (this.options.openCardWidth - 1);
				} else {
					openPositionIndex = 0;
				}
			} else if (spaceLeft < spaceRight) {
				if (spaceRight >= this.options.openCardWidth - 1) { //check if there is enough space to fit to the right
					openPositionIndex = openCardPosition - 1;
				} else {
					openPositionIndex = rowWidth - this.options.openCardWidth -1;
				}
			} else {
				openPositionIndex = openCardPosition - 2;
			}

			// Get the raw height of the open card and stretch to fit the grid
			var openCardHeight, openCardRowHeight, openCardWidth;
			openCardWidth      = (this.options.openCardWidth * (this.options.closedOuterWidth + this.options.margin)) - this.options.margin
			openCardHeight     = document.id(this.openCard).retrieve('instance').getOpenHeight(openCardWidth - (this.options.closedOuterWidth - this.options.closedInnerWidth));
			openCardHeightRows = Math.ceil((openCardHeight+this.options.margin) / (this.options.margin + this.options.closedOuterHeight));
			openCardHeight     = openCardHeightRows * (this.options.margin + this.options.closedOuterHeight) - this.options.margin;
			openCardHeight    -= this.options.closedOuterHeight - this.options.closedInnerHeight;

			// Collect zero based locations for top left and bottom right
			var openCardIndexes = {
				topLeftX: openPositionIndex,
				topLeftY: openCardRow - 1,
				bottomRightX: openPositionIndex + this.options.openCardWidth - 1,
				bottomRightY: openCardRow - 2 + openCardHeightRows
			}

			// To determine the number of needed rows, determine how many places the open card would occuppy
			var neededSpaces, neededRows;
			neededSpaces = this.options.openCardWidth * openCardHeightRows + amountCards - 1;
			neededRows   = Math.ceil(neededSpaces / rowWidth);

			if (neededRows <= openCardIndexes.bottomRightY) {
				neededRows = openCardIndexes.bottomRightY + 1;
			}

		} else {
      this.container.removeClass('detailview');

			//Determine the number of needed rows
			var neededRows = Math.ceil(amountCards / rowWidth);
		}

		// Set various dimensions
		var containerWidth = (rowWidth * (this.options.closedOuterWidth + this.options.margin)) - this.options.margin + 10;
		this.container.setStyles({
			'width': containerWidth,
			'height': (neededRows * (this.options.closedOuterHeight + this.options.margin))
		});
		$$('#header', '#submenu', '#slideshow').setStyle('width', containerWidth-10);

    // use hard 395 value for IE (ignores margin-right on #descriptions)
    $('descriptions').setStyle('width', $('header').getSize().x - 395);

		// Distribute the cards
		var cardIndex, params, currentCard, done;
		cardIndex = -1;
		done = false;

		for (var row=0; row<neededRows; row++) {
			if (done) break;

			for (var col=0; col<rowWidth; col++) {
				if (openCardIndexes) {
					if (row >= openCardIndexes.topLeftY && row <= openCardIndexes.bottomRightY &&
					    col >= openCardIndexes.topLeftX && col <= openCardIndexes.bottomRightX) {
						continue;
					}
				}

				// Determine top and left offset based on the current row and column
				
				params = {};
				params.top    = (row * (this.options.closedOuterHeight + this.options.margin)) + 5;
				params.left   = (col * (this.options.closedOuterWidth + this.options.margin)) + 5;
				params.width  = this.options.closedInnerWidth;
				params.height = this.options.closedInnerHeight;

				// See if there are cards to position and skip the next one if it is the open card
				if (this.cards[cardIndex+1]) {
					if (this.cards[cardIndex+1].id == this.openCard) {
						if (this.cards[cardIndex+2]) {
							cardIndex += 2;
						} else {
							done = true;
							break;
						}

					} else {
						cardIndex++;
					}

					this.cards[cardIndex].position(params);
				}
			}
		}

		// Finally position the open card (if present)
		if (openCardIndexes) {			
			params.top    = (openCardIndexes.topLeftY * (this.options.closedOuterHeight + this.options.margin)) + 5;
			params.left   = (openCardIndexes.topLeftX * (this.options.closedOuterWidth + this.options.margin)) + 5;
			params.width  = (this.options.openCardWidth * (this.options.closedOuterWidth + this.options.margin)) - this.options.margin - (this.options.closedOuterWidth - this.options.closedInnerWidth);
			params.height = openCardHeight;

			var cardToOpen;
			cardToOpen = document.id(this.openCard).retrieve('instance');
			cardToOpen.position(params);		
		}
	}
});
