$process-grid-cols_cache = {}

process-grid-cols($where)
  // Look at the cache
  if ('' + $where) in $process-grid-cols_cache
    return $process-grid-cols_cache['' + $where]

  // Otherwise do all those things
  $initial_gutter = utilus_get($where, 'gutter')
  $result = 'total_count' 0,
            'cols_widths' (),
            'total_units' ('px' 0px) ('em' 0em) ('rem' 0rem) ('%' 0),
            'gutter' (clone($initial_gutter)),
            'shrinkers' (),
            'cols_indexes' (false),
            'even_gaps' true

  $got_count = utilus_get($where, 'count', 0)
  $actual_count = 0
  $without_units = 0

  for $item in $where
    $item_col = utilus_get($item, '-col')
    if $item_col
      $actual_count = $actual_count + 1

      // Save the indexes for the cols
      push($result[5][1], ($item_col[0] (length($result[5][1]) - 1)))

      // Populate the columns
      $items_unit = utilus_get_unit($item_col)
      if $items_unit
        $index = utilus_get(('px' 1) ('em' 2) ('rem' 3) ('%' 4), unit($items_unit))
        push($result[1][1], $items_unit)
        $result[2][$index][1] = $result[2][$index][1] + unit($items_unit,'')
      else
        push($result[1][1], -1)
        $without_units = $without_units + 1

    // Get the gaps
    $item_gap = utilus_get($item, 'gap')
    if $item_gap or (!$item_gap and type($item_gap) != 'boolean')
      // Set the previous gap if there is a gap
      $result[3][1][length($result[5][1]) - 1] = $item_gap
      if $item_gap != $initial_gutter
        $result[6][1] = false
    else if $items_unit
      // Set the next gap at each column
      $result[3][1][length($result[5][1]) + 1] = clone($initial_gutter)

  // If total count is more than cols described, fill the cols with the rest
  if $got_count > $actual_count
    for $item in 1..($got_count - $actual_count)
      push($result[1][1], -1)
      $without_units = $without_units + 1

  // Calculate unset percents
  if $without_units
    $width = ((100 - $result[2][4][1]) / $without_units)
    for $item, $index in $result[1][1]
      if $item == -1
        $result[1][1][$index] = unit($width,'%')
        $result[2][4][1] = $result[2][4][1] + $width

  // Set the proper total count
  $result[0][1] = length($result[1][1])

  // Calculate shrinkers (total sums of units > 0 including gutters)
  for $unit in utilus_get($result, 'total_units')
    if not unit($unit[1]) in ('' '%')
      $current_unit_width = $unit[1]
      for $gap in $result[3][1]
        if unit($gap) == unit($unit[1])
          $current_unit_width = round($current_unit_width + $gap, 9)
      if $current_unit_width > 0
        push($result[4][1], $current_unit_width)

  $process-grid-cols_cache['' + $where] = $result

  return $result

get_column($where, $name_or_index)
  $name = ''
  $index = 0

  if type($name_or_index) == 'string'
    $name = $name_or_index
    $index = utilus_get($where[5][1], $name)
  else
    $index = $name_or_index
    $name = $where[5][1][$index + 1][0]

  $result = 'name' $name,
            'index' $index,
            'width' $where[1][1][$index],
            'left_gap' $where[3][1][$index],
            'right_gap' utilus_or($where[3][1][$index + 1], 0)

  return $result

kind-grid()
  kind-grid_(arguments)

kind-grid_()
  kind-grid_gutter(arguments)
  kind-grid_nowrap(arguments)

kind-grid_gutter($this)
  $columns = process-grid-cols($this.arguments)

  if $columns[6][1]
    margin-left: -1*$gutter = utilus_get($columns, 'gutter')

  unless utilus_get($this.arguments, '-content')
    padding-right: utilus_get($columns, 'shrinkers')[0]

kind-grid_nowrap($this)
  if retrieve($this.arguments, nowrap ellipsis)
    white-space: nowrap

kind-grid-col($this)
  $columns = process-grid-cols($this.parent.arguments)
  $column = get_column($columns, utilus_get_string($this.arguments))
  width: $column[2][1]

  if absolute in $this.arguments
    position: absolute

  else
    kind(block inline)

    unless utilus_get($this.parent.arguments, '-content')
      $gap = $column[3][1]
      if $gap
        margin-left: $gap

      if utilus_get($this.arguments, 'nowrap')
        unless utilus_get($this.parent.arguments, 'nowrap')
          white-space: nowrap
      else
        if utilus_get($this.parent.arguments, 'ellipsis')
          white-space: nowrap unless utilus_get($this.parent.arguments, 'nowrap')
          overflow: hidden
          text-overflow: ellipsis
        else
          white-space: normal

kind-grid-content($this)
  $gutter = utilus_get($this.parent.arguments, 'gutter')
  if $gutter
    margin-left: $gutter
