// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of layout;

// This file has classes representing the grid tracks and grid template

/**
 * The data structure representing the grid-rows or grid-columns
 * properties.
 */
class GridTrackList {
  /** The set of tracks defined in CSS via grid-rows and grid-columns */
  final List<GridTrack> tracks;

  /**
   * Maps edge names to the corresponding track. Depending on whether the index
   * is used as a start or end, it might be interpreted exclusively or
   * inclusively.
   */
  final Map<String, int> lineNames;

  GridTrackList(this.tracks, this.lineNames) {}
}


/** Represents a row or a column. */
class GridTrack {
  /**
   * The start position of this track. Equal to the sum of previous track's
   * usedBreadth.
   */
  num start;

  /** The final computed breadth of this track. */
  num usedBreadth;

  // Fields used internally by the sizing algorithm
  num maxBreadth;
  num updatedBreadth;
  num tempBreadth;

  final TrackSizing sizing;

  GridTrack(this.sizing) {}

  /**
   * Support for the feature that repeats rows and columns, e.g.
   * [:grid-columns: 10px ("content" 250px 10px)[4]:]
   */
  GridTrack clone() => new GridTrack(sizing.clone());

  /** The min sizing function for the track. */
  SizingFunction get minSizing => sizing.min;

  /** The min sizing function for the track. */
  SizingFunction get maxSizing => sizing.max;

  num get end => start + usedBreadth;

  bool get isFractional => minSizing.isFraction || maxSizing.isFraction;
}


/** Represents the grid-row-align or grid-column-align. */
class GridItemAlignment {
  // TODO(jmesserly): should this be stored as an int for performance?
  final String value;

  // 'start' | 'end' | 'center' | 'stretch'
  GridItemAlignment.fromString(String value)
    : this.value = (value == null) ? 'stretch' : value {

      switch (this.value) {
      case 'start': case 'end': case 'center': case 'stretch':
        break;
      default:
        throw new UnsupportedError(
            'invalid row/column alignment "$value"');
    }
  }

  _GridLocation align(_GridLocation span, int size) {
    switch (value) {
      case 'start':
        return new _GridLocation(span.start, size);
      case 'end':
        return new _GridLocation(span.end - size, size);
      case 'center':
        size = Math.min(size, span.length);
        num center = span.start + span.length / 2;
        num left = center - size / 2;
        return new _GridLocation(left.round(), size);
      case 'stretch':
        return span;
    }
  }
}


/**
 * Represents a grid-template. Used in conjunction with a grid-cell to
 * place cells in the grid, without needing to specify the exact row/column.
 */
class GridTemplate {
  final Map<int, _GridTemplateRect> _rects;
  final int _numRows;

  GridTemplate(List<String> rows)
    : _rects = new Map<int, _GridTemplateRect>(),
      _numRows = rows.length {
    _buildRects(rows);
  }

  /** Scans the template strings and computes bounds for each one. */
  void _buildRects(List<String> templateRows) {
    for (int r = 0; r < templateRows.length; r++) {
      String row = templateRows[r];
      for (int c = 0; c < row.length; c++) {
        int cell = row.codeUnitAt(c);
        final rect = _rects[cell];
        if (rect != null) {
          rect.add(r + 1, c + 1);
        } else {
          _rects[cell] = new _GridTemplateRect(cell, r + 1, c + 1);
        }
      }
    }

    // Finally, check that each rectangle is valid (i.e. all spaces filled)
    for (final rect in _rects.values) {
      rect.checkValid();
    }
  }

  /**
   * Looks up the given cell in the template, and returns the rect.
   */
  _GridTemplateRect lookupCell(String cell) {
    if (cell.length != 1) {
      throw new UnsupportedError(
          'grid-cell "$cell" must be a one character string');
    }
    final rect = _rects[cell.codeUnitAt(0)];
    if (rect == null) {
      throw new UnsupportedError(
        'grid-cell "$cell" not found in parent\'s grid-template');
    }
    return rect;
  }
}

/** Used by GridTemplate to track a single cell's bounds. */
class _GridTemplateRect {
  int row, column, rowSpan, columnSpan, _count, _char;
  _GridTemplateRect(this._char, this.row, this.column)
    : rowSpan = 1, columnSpan = 1, _count = 1 {}

  void add(int r, int c) {
    assert (r >= row && c >= column);
    _count++;
    rowSpan = Math.max(rowSpan, r - row + 1);
    columnSpan = Math.max(columnSpan, c - column + 1);
  }

  void checkValid() {
    int expected = rowSpan * columnSpan;
    if (expected != _count) {
      // TODO(jmesserly): not sure if we should throw here, due to CSS's
      // permissiveness. At the moment we're noisy about errors.
      String cell = new String.fromCharCodes([_char]);
      throw new UnsupportedError('grid-template "$cell"'
          ' is not square, expected $expected cells but got $_count');
    }
  }
}


/**
 * Used to return a row/column and span during parsing of grid-row and
 * grid-column during parsing.
 */
class _GridLocation {
  final int start, length;
  _GridLocation(this.start, this.length) {}

  int get end => start + length;
}
