// Copyright (c) 2015, 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.

library dart_style.src.nesting_builder;

import 'nesting_level.dart';
import 'whitespace.dart';

/// Keeps track of block indentation and expression nesting while the source
/// code is being visited and the chunks are being built.
///
/// This class requires (and verifies) that indentation and nesting are
/// stratified from each other. Expression nesting is always inside block
/// indentation, which means it is an error to try to change the block
/// indentation while any expression nesting is in effect.
class NestingBuilder {
  /// The block indentation levels.
  ///
  /// This is tracked as a stack of numbers, each of which is the total number
  /// of spaces of block indentation. We only store the stack of previous
  /// levels as a convenience to the caller: it spares you from having to pass
  /// the unindent amount to [unindent()].
  final List<int> _stack = [0];

  /// When not `null`, the expression nesting after the next token is written.
  ///
  /// When the nesting is increased, we don't want it to take effect until
  /// after at least one token has been written. That ensures that comments
  /// appearing before the first token are correctly indented. For example, a
  /// binary operator expression increases the nesting before the first operand
  /// to ensure any splits within the left operand are handled correctly. If we
  /// changed the nesting level immediately, then code like:
  ///
  ///     {
  ///       // comment
  ///       foo + bar;
  ///     }
  ///
  /// would incorrectly get indented because the line comment adds a split which
  /// would take the nesting level of the binary operator into account even
  /// though we haven't written any of its tokens yet.
  ///
  /// Likewise, when nesting is decreased, we may want to defer that until
  /// we've written the next token to handle uncommon cases like:
  ///
  ///     do // comment
  ///         {
  ///       ...
  ///     }
  ///
  /// Here, if we discard the expression nesting before we reach the "{", then
  /// it won't get indented as it should.
  NestingLevel _pendingNesting;

  /// The current number of characters of block indentation.
  int get indentation => _stack.last;

  /// The current nesting, ignoring any pending nesting.
  NestingLevel get nesting => _nesting;
  NestingLevel _nesting = new NestingLevel();

  /// The current nesting, including any pending nesting.
  NestingLevel get currentNesting =>
      _pendingNesting != null ? _pendingNesting : _nesting;

  /// The top "nesting level" that represents no expression nesting for the
  /// current block.
  NestingLevel get blockNesting {
    // Walk the nesting levels until we bottom out.
    var result = _nesting;
    while (result.parent != null) {
      result = result.parent;
    }
    return result;
  }

  /// Creates a new indentation level [spaces] deeper than the current one.
  ///
  /// If omitted, [spaces] defaults to [Indent.block].
  void indent([int spaces]) {
    if (spaces == null) spaces = Indent.block;

    // Indentation should only change outside of nesting.
    assert(_pendingNesting == null);
    assert(_nesting.indent == 0);

    _stack.add(_stack.last + spaces);
  }

  /// Discards the most recent indentation level.
  void unindent() {
    // Indentation should only change outside of nesting.
    assert(_pendingNesting == null);
    assert(_nesting.indent == 0);

    // If this fails, an unindent() call did not have a preceding indent() call.
    assert(_stack.isNotEmpty);

    _stack.removeLast();
  }

  /// Begins a new expression nesting level [indent] deeper than the current
  /// one if it splits.
  ///
  /// Expressions that are more nested will get increased indentation when split
  /// if the previous line has a lower level of nesting.
  ///
  /// If [indent] is omitted, defaults to [Indent.expression].
  void nest([int indent]) {
    if (indent == null) indent = Indent.expression;

    if (_pendingNesting != null) {
      _pendingNesting = _pendingNesting.nest(indent);
    } else {
      _pendingNesting = _nesting.nest(indent);
    }
  }

  /// Discards the most recent level of expression nesting.
  void unnest() {
    if (_pendingNesting != null) {
      _pendingNesting = _pendingNesting.parent;
    } else {
      _pendingNesting = _nesting.parent;
    }

    // If this fails, an unnest() call did not have a preceding nest() call.
    assert(_pendingNesting != null);
  }

  /// Applies any pending nesting now that we are ready for it to take effect.
  void commitNesting() {
    if (_pendingNesting == null) return;

    _nesting = _pendingNesting;
    _pendingNesting = null;
  }
}
