// 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;

/**
 * Implements a grid-based layout system based on:
 * [http://dev.w3.org/csswg/css3-grid-align/]
 *
 * This layout is designed to support animations and work on browsers that
 * don't support grid natively. As such, we implement it on top of absolute
 * positioning.
 */
// TODO(jmesserly): the DOM integration still needs work:
//  - The grid assumes it is absolutely positioned in its container.
//    Because of that, the grid doesn't work right unless it has at least one
//    fractional size in each dimension. In other words, only "top down" grids
//    work at the moment, because the grid can't determine its own size.
//    The core algorithm supports computing min breadth; the issue is about how
//    to integrate it into our View layer.
//  - Unless a child element is "display: inline-block" we can't get its
//    horizontal content size.
//  - Once we set an element's size to "position: absolute", we lose the
//    ability to get its original content size. If the width or height gets
//    set to something other than the content size, we can't recover the
//    original content size.
//  - There's some rounding to ints when we want to set the positions of our
//    tracks. I don't think we necessarily need to do that.
//
// TODO(jmesserly): Some features of the spec are unimplemented:
//  - grid-flow & items that have row and column set to 'auto'.
//  - Grid writing modes (right to left languages, etc)
//  - We don't do a second calculation pass if min content size of a grid-item
//    changes due to column width.
//  - The CSS parsing is not 100% complete, see the parser TODOs.
//  - We don't implement error recovery for invalid combinations of CSS
//    properties, or invalid CSS property values. Instead we throw an error.
//
// TODO(jmesserly): high level performance optimizations we could do:
//  - Optimize for the common case of spanCount = 1
//  - Optimize for the vbox/hbox case (1 row or 1 column)
//  - Optimize for the case of no content sized tracks
//  - Optimize for the "incremental update" cases
class GridLayout extends ViewLayout {
  /** Configuration parameters defined in CSS. */
  final GridTrackList rows;
  final GridTrackList columns;
  final GridTemplate template;

  /** The default sizing for new rows. */
  final TrackSizing rowSizing;

  /** The default sizing for new columns. */
  final TrackSizing columnSizing;

  /**
   * This stores the grid's size during a layout.
   * Used for rows/columns with % or fr units.
   */
  int _gridWidth, _gridHeight;

  /**
   * During a layout, this stores all row/column size information.
   * Because grid-items can implicitly specify their own rows/columns, we can't
   * compute this until we know the set of items.
   */
  List<GridTrack> _rowTracks, _columnTracks;

  /** During a layout, tracks which dimension we're processing. */
  Dimension _dimension;

  GridLayout(Positionable view)
      : rows = _GridTrackParser.parse(view.customStyle['grid-rows']),
        columns = _GridTrackParser.parse(view.customStyle['grid-columns']),
        template = _GridTemplateParser.parse(view.customStyle['grid-template']),
        rowSizing = _GridTrackParser
            .parseTrackSizing(view.customStyle['grid-row-sizing']),
        columnSizing = _GridTrackParser
            .parseTrackSizing(view.customStyle['grid-column-sizing']),
        super(view) {
    _rowTracks = rows != null ? rows.tracks : new List<GridTrack>();
    _columnTracks = columns != null ? columns.tracks : new List<GridTrack>();
  }

  int get currentWidth => _gridWidth;
  int get currentHeight => _gridHeight;

  void cacheExistingBrowserLayout() {
    // We don't need to do anything as we don't rely on the _cachedViewRect
    // when the grid layout is used.
  }

  // TODO(jacobr): cleanup this method so that it returns a Future
  // rather than taking a Completer as an argument.
  /** The main entry point for layout computation. */
  void measureLayout(Future<Size> size, Completer<bool> changed) {
    _ensureAllTracks();
    size.then((value) {
      _gridWidth = value.width;
      _gridHeight = value.height;

      if (_rowTracks.length > 0 && _columnTracks.length > 0) {
        _measureTracks();
        _setBoundsOfChildren();
        if (changed != null) {
          changed.complete(true);
        }
      }
    });
  }

  /**
   * The top level measurement function.
   * [http://dev.w3.org/csswg/css3-grid-align/#calculating-size-of-grid-tracks]
   */
  void _measureTracks() {
    // Resolve logical width, then height. Width comes first so we can use
    // the width when determining the content-sized height.
    try {
      _dimension = Dimension.WIDTH;
      _computeUsedBreadthOfTracks(_columnTracks);
      _dimension = Dimension.HEIGHT;
      _computeUsedBreadthOfTracks(_rowTracks);
    } finally {
      _dimension = null;
    }

    // TODO(jmesserly): we're supposed to detect a min-content size change
    // due to our computed width and trigger a new layout.
    // How do we implement that?
  }

  num _getRemainingSpace(List<GridTrack> tracks) {
    num remaining = _getGridContentSize();
    remaining -= CollectionUtils.sum(tracks, (t) => t.usedBreadth);
    return Math.max(0, remaining);
  }

  /**
   * This is the core Grid Track sizing algorithm. It is run for Grid columns
   * and Grid rows. The goal of the function is to ensure:
   *   1. That each Grid Track satisfies its minSizing
   *   2. That each Grid Track grows from the breadth which satisfied its
   *      minSizing to a breadth which satifies its
   *      maxSizing, subject to RemainingSpace.
   */
  // Note: spec does not correctly doc all the parameters to this function.
  void _computeUsedBreadthOfTracks(List<GridTrack> tracks) {
    // TODO(jmesserly): as a performance optimization we could cache this
    final items = view.childViews.map((view_) => view_.layout).toList();
    CollectionUtils.sortBy(items, (item) => _getSpanCount(item));

    // 1. Initialize per Grid Track variables
    for (final t in tracks) {
      // percentage or length sizing functions will return a value
      // min-content, max-content, or a fraction will be set to 0
      t.usedBreadth = t.minSizing.resolveLength(_getGridContentSize());
      t.maxBreadth = t.maxSizing.resolveLength(_getGridContentSize());
      t.updatedBreadth = 0;
    }

    // 2. Resolve content-based MinTrackSizingFunctions
    final USED_BREADTH = const _UsedBreadthAccumulator();
    final MAX_BREADTH = const _MaxBreadthAccumulator();

    _distributeSpaceBySpanCount(items, ContentSizeMode.MIN, USED_BREADTH);

    _distributeSpaceBySpanCount(items, ContentSizeMode.MAX, USED_BREADTH);

    // 3. Ensure that maxBreadth is as big as usedBreadth for each track
    for (final t in tracks) {
      if (t.maxBreadth < t.usedBreadth) {
        t.maxBreadth = t.usedBreadth;
      }
    }

    // 4. Resolve content-based MaxTrackSizingFunctions
    _distributeSpaceBySpanCount(items, ContentSizeMode.MIN, MAX_BREADTH);

    _distributeSpaceBySpanCount(items, ContentSizeMode.MAX, MAX_BREADTH);

    // 5. Grow all Grid Tracks in GridTracks from their usedBreadth up to their
    //    maxBreadth value until RemainingSpace is exhausted.
    // Note: it's not spec'd what to pass as the accumulator, but usedBreadth
    // seems right.
    _distributeSpaceToTracks(
        tracks, _getRemainingSpace(tracks), USED_BREADTH, false);

    // Spec wording is confusing about which direction this assignment happens,
    // but this is the way that makes sense.
    for (final t in tracks) {
      t.usedBreadth = t.updatedBreadth;
    }

    // 6. Grow all Grid Tracks having a fraction as their maxSizing
    final tempBreadth = _calcNormalizedFractionBreadth(tracks);
    for (final t in tracks) {
      t.usedBreadth =
          Math.max(t.usedBreadth, tempBreadth * t.maxSizing.fractionValue);
    }

    _computeTrackPositions(tracks);
  }

  /**
   * Final steps to finish positioning tracks. Takes the track size and uses
   * it to get start and end positions. Also rounds the positions to integers.
   */
  void _computeTrackPositions(List<GridTrack> tracks) {
    // Compute start positions of tracks, as well as the final position

    num position = 0;
    for (final t in tracks) {
      t.start = position;
      position += t.usedBreadth;
    }

    // Now, go through and round each position to an integer. Then
    // compute the sizes based on those integers.
    num finalPosition = position;

    for (int i = 0; i < tracks.length; i++) {
      int startEdge = tracks[i].start;
      int endEdge;
      if (i < tracks.length - 1) {
        endEdge = tracks[i + 1].start.round();
        tracks[i + 1].start = endEdge;
      } else {
        endEdge = finalPosition.round();
      }
      int breadth = endEdge - startEdge;

      // check that we're not off by >= 1px.
      assert((endEdge - startEdge - tracks[i].usedBreadth).abs() < 1);

      tracks[i].usedBreadth = breadth;
    }
  }

  /**
   * This method computes a '1fr' value, referred to as the
   * tempBreadth, for a set of Grid Tracks. The value computed
   * will ensure that when the tempBreadth is multiplied by the
   * fractions associated with tracks, that the UsedBreadths of tracks
   * will increase by an amount equal to the maximum of zero and the specified
   * freeSpace less the sum of the current UsedBreadths.
   */
  num _calcNormalizedFractionBreadth(List<GridTrack> tracks) {
    final fractionTracks = tracks.where((t) => t.maxSizing.isFraction).toList();

    // Note: the spec has various bugs in this function, such as mismatched
    // identifiers and names that aren't defined. For the most part it's
    // possible to figure out the meaning. It's also a bit confused about
    // how to compute spaceNeededFromFractionTracks, but that should just be the
    // set to the remaining free space after usedBreadth is accounted for.

    // We use the tempBreadth field to store the normalized fraction breadth
    for (final t in fractionTracks) {
      t.tempBreadth = t.usedBreadth / t.maxSizing.fractionValue;
    }

    CollectionUtils.sortBy(fractionTracks, (t) => t.tempBreadth);

    num spaceNeededFromFractionTracks = _getRemainingSpace(tracks);
    num currentBandFractionBreadth = 0;
    num accumulatedFractions = 0;
    for (final t in fractionTracks) {
      if (t.tempBreadth != currentBandFractionBreadth) {
        if (t.tempBreadth * accumulatedFractions >
            spaceNeededFromFractionTracks) {
          break;
        }
        currentBandFractionBreadth = t.tempBreadth;
      }
      accumulatedFractions += t.maxSizing.fractionValue;
      spaceNeededFromFractionTracks += t.usedBreadth;
    }
    return spaceNeededFromFractionTracks / accumulatedFractions;
  }

  /**
   * Ensures that for each Grid Track in tracks, a value will be
   * computed, updatedBreadth, that represents the Grid Track's share of
   * freeSpace.
   */
  void _distributeSpaceToTracks(List<GridTrack> tracks, num freeSpace,
      _BreadthAccumulator breadth, bool ignoreMaxBreadth) {
    // TODO(jmesserly): in some cases it would be safe to sort the passed in
    // list in place. Not always though.
    tracks = CollectionUtils.orderBy(
        tracks, (t) => t.maxBreadth - breadth.getSize(t));

    // Give each Grid Track an equal share of the space, but without exceeding
    // their maxBreadth values. Because there are different MaxBreadths
    // assigned to the different Grid Tracks, this can result in uneven growth.
    for (int i = 0; i < tracks.length; i++) {
      num share = freeSpace / (tracks.length - i);
      share = Math.min(share, tracks[i].maxBreadth);
      tracks[i].tempBreadth = share;
      freeSpace -= share;
    }

    // If the first loop completed having grown every Grid Track to its
    // maxBreadth, and there is still freeSpace, then divide that space
    // evenly and assign it to each Grid Track without regard for its
    // maxBreadth. This phase of growth will always be even, but only occurs
    // when the ignoreMaxBreadth flag is true.
    if (freeSpace > 0 && ignoreMaxBreadth) {
      for (int i = 0; i < tracks.length; i++) {
        final share = freeSpace / (tracks.length - i);
        tracks[i].tempBreadth += share;
        freeSpace -= share;
      }
    }

    // Note: the spec has us updating all grid tracks, not just the passed in
    // tracks, but I think that's a spec bug.
    for (final t in tracks) {
      t.updatedBreadth = Math.max(t.updatedBreadth, t.tempBreadth);
    }
  }

  /**
   * This function prioritizes the distribution of space driven by Grid Items
   * in content-sized Grid Tracks by the Grid Item's spanCount. That is, Grid
   * Items having a lower spanCount have an opportunity to increase the size of
   * the Grid Tracks they cover before those with larger SpanCounts.
   *
   * Note: items are assumed to be already sorted in increasing span count
   */
  void _distributeSpaceBySpanCount(List<ViewLayout> items,
      ContentSizeMode sizeMode, _BreadthAccumulator breadth) {
    items = items
        .where((item) =>
            _hasContentSizedTracks(_getTracks(item), sizeMode, breadth))
        .toList();

    var tracks = [];

    for (int i = 0; i < items.length; i++) {
      final item = items[i];

      final itemTargetSize = item.measureContent(this, _dimension, sizeMode);

      final spannedTracks = _getTracks(item);
      _distributeSpaceToTracks(spannedTracks, itemTargetSize, breadth, true);

      // Remember that we need to update the sizes on these tracks
      tracks.addAll(spannedTracks);

      // Each time we transition to a new spanCount, update any modified tracks
      bool spanCountFinished = false;
      if (i + 1 == items.length) {
        spanCountFinished = true;
      } else if (_getSpanCount(item) != _getSpanCount(items[i + 1])) {
        spanCountFinished = true;
      }

      if (spanCountFinished) {
        for (final t in tracks) {
          breadth.setSize(t, Math.max(breadth.getSize(t), t.updatedBreadth));
        }
        tracks = [];
      }
    }
  }

  /**
   * Returns true if we have an appropriate content sized dimension, and don't
   * cross a fractional track.
   */
  static bool _hasContentSizedTracks(Iterable<GridTrack> tracks,
      ContentSizeMode sizeMode, _BreadthAccumulator breadth) {
    for (final t in tracks) {
      final fn = breadth.getSizingFunction(t);
      if (sizeMode == ContentSizeMode.MAX && fn.isMaxContentSized ||
          sizeMode == ContentSizeMode.MIN && fn.isContentSized) {
        // Make sure we don't cross a fractional track
        return tracks.length == 1 || !tracks.any((t_) => t_.isFractional);
      }
    }
    return false;
  }

  /** Ensures that the numbered track exists. */
  void _ensureTrack(
      List<GridTrack> tracks, TrackSizing sizing, int start, int span) {
    // Start is 1-based. Make it 0-based.
    start -= 1;

    // Grow the list if needed
    int length = start + span;
    int first = Math.min(start, tracks.length);
    tracks.length = Math.max(tracks.length, length);

    // Fill in tracks
    for (int i = first; i < length; i++) {
      if (tracks[i] == null) {
        tracks[i] = new GridTrack(sizing);
      }
    }
  }

  /**
   * Scans children creating GridLayoutParams as needed, and creates all of the
   * rows and columns that we will need.
   *
   * Note: this can potentially create new rows/columns, so this needs to be
   * run before the track sizing algorithm.
   */
  void _ensureAllTracks() {
    final items = view.childViews.map((view_) => view_.layout);

    for (final child in items) {
      if (child.layoutParams == null) {
        final p = new GridLayoutParams(child.view, this);
        _ensureTrack(_rowTracks, rowSizing, p.row, p.rowSpan);
        _ensureTrack(_columnTracks, columnSizing, p.column, p.columnSpan);
        child.layoutParams = p;
      }
      child.cacheExistingBrowserLayout();
    }
  }

  /**
   * Given the track sizes that were computed, position children in the grid.
   */
  void _setBoundsOfChildren() {
    final items = view.childViews.map((view_) => view_.layout);

    for (final item in items) {
      GridLayoutParams childLayout = item.layoutParams;
      var xPos = _getTrackLocationX(childLayout);
      var yPos = _getTrackLocationY(childLayout);

      int left = xPos.start, width = xPos.length;
      int top = yPos.start, height = yPos.length;

      // Somewhat counterintuitively (at least to me):
      //   grid-col-align is the horizontal alignment
      //   grid-row-align is the vertical alignment
      xPos = childLayout.columnAlign.align(xPos, item.currentWidth);
      yPos = childLayout.rowAlign.align(yPos, item.currentHeight);

      item.setBounds(xPos.start, yPos.start, xPos.length, yPos.length);
    }
  }

  num _getGridContentSize() {
    if (_dimension == Dimension.WIDTH) {
      return _gridWidth;
    } else if (_dimension == Dimension.HEIGHT) {
      return _gridHeight;
    }
  }

  _GridLocation _getTrackLocationX(GridLayoutParams childLayout) {
    int start = childLayout.column - 1;
    int end = start + childLayout.columnSpan - 1;

    start = _columnTracks[start].start;
    end = _columnTracks[end].end;

    return new _GridLocation(start, end - start);
  }

  _GridLocation _getTrackLocationY(GridLayoutParams childLayout) {
    int start = childLayout.row - 1;
    int end = start + childLayout.rowSpan - 1;

    start = _rowTracks[start].start;
    end = _rowTracks[end].end;

    return new _GridLocation(start, end - start);
  }

  /** Gets the tracks that this item crosses. */
  // TODO(jmesserly): might be better to return an iterable
  List<GridTrack> _getTracks(ViewLayout item) {
    GridLayoutParams childLayout = item.layoutParams;

    int start, span;
    List<GridTrack> tracks;
    if (_dimension == Dimension.WIDTH) {
      start = childLayout.column - 1;
      span = childLayout.columnSpan;
      tracks = _columnTracks;
    } else if (_dimension == Dimension.HEIGHT) {
      start = childLayout.row - 1;
      span = childLayout.rowSpan;
      tracks = _rowTracks;
    }

    assert(start >= 0 && span >= 1);

    final result = new List<GridTrack>(span);
    for (int i = 0; i < span; i++) {
      result[i] = tracks[start + i];
    }
    return result;
  }

  int _getSpanCount(ViewLayout item) {
    GridLayoutParams childLayout = item.layoutParams;
    return (_dimension == Dimension.WIDTH
        ? childLayout.columnSpan
        : childLayout.rowSpan);
  }
}
