$(function() {
  
  var cell = {
    unit: {
      width:   195,
      height:  238
    },
    normal: {
      rows: 1,
      cols: 1
    },
    expanded: {
      cols: 4,
      rows: 2
    }
  }
  
  var selectors = {
    single:       '.cell',
    container:    '.cells',
    all:          '.cells>li',
    not_expanded: '.cells>li:not(.expanded)',
    expanded:     '.cells>li.expanded'
  }
  
  function calculate_container() {
    var result = {};
    result.width = $(selectors.container).width();
    result.cells = $(selectors.all).length;    
    result.cols = Math.floor(result.width / cell.unit.width);
    result.rows = Math.ceil(result.cells / result.cols);
    result.edge = result.cols - cell.expanded.cols;
    result.height = result.rows * cell.unit.height;
    return result;
  }
  var container = calculate_container();
  $(selectors.container).height(container.height);
  
  var coords_of_cell = function(i) {
    return {
      x: (i % container.cols) * cell.unit.width,
      y: Math.floor((i / container.cols)) * cell.unit.height
    }
  }

  // TODO: make this method public
  XM.update = function() {
    var matrix = new Array(container.cols * container.rows + cell.expanded.cols + cell.expanded.rows);
    
    var expanded   = $(selectors.expanded)[0];

    if (expanded) {
      var grid_x = Math.floor( $(expanded).position().left / cell.unit.width  );
      var grid_y = Math.floor( $(expanded).position().top  / cell.unit.height );
      var expanded_i = grid_x + (grid_y * container.cols);

      if (expanded_i > -1) {
        var expanded_col = expanded_i % container.cols;
        
        var overflow = (expanded_col > container.edge) ? expanded_col - container.edge : 0;

        if (overflow > 0) {
          expanded_i -= overflow;
        }
        
        /* user clicked an item on the second to the last row, column midway across */
        /* so it will drop down to the next row, AFTER any existing cells */
        /* which is not what we want. */
        /* so, just back it up to be the very last cell instead */
        if (expanded_i > $(selectors.not_expanded).length) {
          expanded_i = $(selectors.not_expanded).length;
        }
        
        /* TODO handle "overhang", where cell is in a top row, but overlays an empty bottom row */
        /* TODO make fill dynamic based on the number of cells in an expanded cell rows/cols */
        
        /* fill */
        var n = expanded_i;
        var a = n,
            b = n + 1,
            c = n + container.cols,
            d = n + 1 + container.cols,
            e = n + 2,
            f = n + 2 + container.cols,
            g = n + 3,
            h = n + 3 + container.cols;
        matrix[a] = true;
        matrix[b] = true;
        matrix[c] = true;
        matrix[d] = true;
        matrix[e] = true;
        matrix[f] = true;
        matrix[g] = true;
        matrix[h] = true;
    
        $(expanded).css("left",  coords_of_cell(expanded_i).x);
        $(expanded).css("top",   coords_of_cell(expanded_i).y);
      }
    }
    
    /* position all the cells _not_ expanded */
    var not_exp = $.makeArray($(selectors.not_expanded));
    $.each(matrix, function(n, marked) {
      if ( !marked ) {
        var cell = $(not_exp.shift());
        var pos = coords_of_cell(n);
        $(cell).css("left", pos.x);
        $(cell).css("top", pos.y);
      }
    });
    setHeaderWidth();
    setContainerHeight(expanded_i);
  }

  var setHeaderWidth = function() {
    header = calculate_container();
    $('#Header').width(Math.floor(header.cols * cell.unit.width - 10));
  }
  
  var setContainerHeight = function(index) {
    container = calculate_container();
    if (coords_of_cell(index).y + (cell.unit.height * cell.expanded.rows) > Math.floor(container.rows * cell.unit.height)) container.rows++;
    $('ul.cells').height((container.rows + 1) * cell.unit.height);
  }
  
  /*** ALL THIS IS NOW HANDLED BY THE PRODUCT VIEW CLASS ***/
  
  // $(selectors.single+' a').mousedown(function() {
  //   $(selectors.single).removeClass("expanded");
  //   $(this).parent(selectors.single).addClass("expanded");
  //   // XM.update();  << This is now defined on the ProductView event listener
  //   return false;
  // });
  
  /********************************************************/
  
  // NOTE: fiddly.
  $(window).resize(function() {
    container = calculate_container();
    XM.update();
  });
  
  XM.update();
  
});