// Copyright (c) 2014, 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.call_chain_visitor;

import 'package:analyzer/analyzer.dart';

import 'argument_list_visitor.dart';
import 'rule/argument.dart';
import 'rule/rule.dart';
import 'source_visitor.dart';

/// Helper class for [SourceVisitor] that handles visiting and writing a
/// chained series of method invocations, property accesses, and/or prefix
/// expressions. In other words, anything using the "." operator.
class CallChainVisitor {
  final SourceVisitor _visitor;

  /// The initial target of the call chain.
  ///
  /// This may be any expression except [MethodInvocation], [PropertyAccess] or
  /// [PrefixedIdentifier].
  final Expression _target;

  /// The list of dotted names ([PropertyAccess] and [PrefixedIdentifier] at
  /// the start of the call chain.
  ///
  /// This will be empty if the [_target] is not a [SimpleIdentifier].
  final List<Expression> _properties;

  /// The mixed method calls and property accesses in the call chain in the
  /// order that they appear in the source.
  final List<Expression> _calls;

  /// The method calls containing block function literals that break the method
  /// chain and escape its indentation.
  ///
  ///     receiver.a().b().c(() {
  ///       ;
  ///     }).d(() {
  ///       ;
  ///     }).e();
  ///
  /// Here, it will contain `c` and `d`.
  ///
  /// The block calls must be contiguous and must be a suffix of the list of
  /// calls (except for the one allowed hanging call). Otherwise, none of them
  /// are treated as block calls:
  ///
  ///     receiver
  ///         .a()
  ///         .b(() {
  ///           ;
  ///         })
  ///         .c(() {
  ///           ;
  ///         })
  ///         .d()
  ///         .e();
  final List<Expression> _blockCalls;

  /// If there is one or more block calls and a single chained expression after
  /// that, this will be that expression.
  ///
  ///     receiver.a().b().c(() {
  ///       ;
  ///     }).d(() {
  ///       ;
  ///     }).e();
  ///
  /// We allow a single hanging call after the blocks because it will never
  /// need to split before its `.` and this accommodates the common pattern of
  /// a trailing `toList()` or `toSet()` after a series of higher-order methods
  /// on an iterable.
  final Expression _hangingCall;

  /// Whether or not a [Rule] is currently active for the call chain.
  bool _ruleEnabled = false;

  /// Whether or not the span wrapping the call chain is currently active.
  bool _spanEnded = false;

  /// After the properties are visited (if there are any), this will be the
  /// rule used to split between them.
  PositionalRule _propertyRule;

  /// Creates a new call chain visitor for [visitor] starting with [node].
  ///
  /// The [node] is the outermost expression containing the chained "."
  /// operators and must be a [MethodInvocation], [PropertyAccess] or
  /// [PrefixedIdentifier].
  factory CallChainVisitor(SourceVisitor visitor, Expression node) {
    var target;

    // Recursively walk the chain of calls and turn the tree into a list.
    var calls = [];
    flatten(expression) {
      target = expression;

      // Treat index expressions where the target is a valid call in a method
      // chain as being part of the call. Handles cases like:
      //
      //     receiver
      //         .property
      //         .property[0]
      //         .property
      //         .method()[1][2];
      var call = expression;
      while (call is IndexExpression) call = call.target;

      if (call is MethodInvocation && call.target != null) {
        flatten(call.target);
        calls.add(expression);
      } else if (call is PropertyAccess && call.target != null) {
        flatten(call.target);
        calls.add(expression);
      } else if (call is PrefixedIdentifier) {
        flatten(call.prefix);
        calls.add(expression);
      }
    }

    flatten(node);

    // An expression that starts with a series of dotted names gets treated a
    // little specially. We don't force leading properties to split with the
    // rest of the chain. Allows code like:
    //
    //     address.street.number
    //       .toString()
    //       .length;
    var properties = [];
    if (target is SimpleIdentifier) {
      properties = calls.takeWhile((call) {
        // Step into index expressions to see what the index is on.
        while (call is IndexExpression) call = call.target;
        return call is! MethodInvocation;
      }).toList();
    }

    calls.removeRange(0, properties.length);

    // Separate out the block calls, if there are any.
    var blockCalls;
    var hangingCall;

    var inBlockCalls = false;
    for (var call in calls) {
      // See if this call is a method call whose arguments are block formatted.
      var isBlockCall = false;
      if (call is MethodInvocation) {
        var args = new ArgumentListVisitor(visitor, call.argumentList);
        isBlockCall = args.hasBlockArguments;
      }

      if (isBlockCall) {
        inBlockCalls = true;
        if (blockCalls == null) blockCalls = [];
        blockCalls.add(call);
      } else if (inBlockCalls) {
        // We found a non-block call after a block call.
        if (call == calls.last) {
          // It's the one allowed hanging one, so it's OK.
          hangingCall = call;
          break;
        }

        // Don't allow any of the calls to be block formatted.
        blockCalls = null;
        break;
      }
    }

    if (blockCalls != null) {
      for (var blockCall in blockCalls) calls.remove(blockCall);
    }

    if (hangingCall != null) {
      calls.remove(hangingCall);
    }

    return new CallChainVisitor._(
        visitor, target, properties, calls, blockCalls, hangingCall);
  }

  CallChainVisitor._(this._visitor, this._target, this._properties, this._calls,
      this._blockCalls, this._hangingCall);

  /// Builds chunks for the call chain.
  ///
  /// If [unnest] is `false` than this will not close the expression nesting
  /// created for the call chain and the caller must end it. Used by cascades
  /// to force a cascade after a method chain to be more deeply nested than
  /// the methods.
  void visit({bool unnest}) {
    if (unnest == null) unnest = true;

    _visitor.builder.nestExpression();

    // Try to keep the entire method invocation one line.
    _visitor.builder.startSpan();

    // If a split in the target expression forces the first `.` to split, then
    // start the rule now so that it surrounds the target.
    var splitOnTarget = _forcesSplit(_target);

    if (splitOnTarget) {
      if (_properties.length > 1) {
        _propertyRule = new PositionalRule(null, 0, 0);
        _visitor.builder.startLazyRule(_propertyRule);
      } else if (_calls.isNotEmpty) {
        _enableRule(lazy: true);
      }
    }

    _visitor.visit(_target);

    // Leading properties split like positional arguments: either not at all,
    // before one ".", or before all of them.
    if (_properties.length == 1) {
      _visitor.soloZeroSplit();
      _writeCall(_properties.single);
    } else if (_properties.length > 1) {
      if (!splitOnTarget) {
        _propertyRule = new PositionalRule(null, 0, 0);
        _visitor.builder.startRule(_propertyRule);
      }

      for (var property in _properties) {
        _propertyRule.beforeArgument(_visitor.zeroSplit());
        _writeCall(property);
      }

      _visitor.builder.endRule();
    }

    // Indent any block arguments in the chain that don't get special formatting
    // below. Only do this if there is more than one argument to avoid spurious
    // indentation in cases like:
    //
    //     object.method(wrapper(() {
    //       body;
    //     });
    // TODO(rnystrom): Come up with a less arbitrary way to express this?
    if (_calls.length > 1) _visitor.builder.startBlockArgumentNesting();

    // The chain of calls splits atomically (either all or none). Any block
    // arguments inside them get indented to line up with the `.`.
    for (var call in _calls) {
      _enableRule();
      _visitor.zeroSplit();
      _writeCall(call);
    }

    if (_calls.length > 1) _visitor.builder.endBlockArgumentNesting();

    // If there are block calls, end the chain and write those without any
    // extra indentation.
    if (_blockCalls != null) {
      _enableRule();
      _visitor.zeroSplit();
      _disableRule();

      for (var blockCall in _blockCalls) {
        _writeBlockCall(blockCall);
      }

      // If there is a hanging call after the last block, write it without any
      // split before the ".".
      if (_hangingCall != null) {
        _writeCall(_hangingCall);
      }
    }

    _disableRule();
    _endSpan();

    if (unnest) _visitor.builder.unnest();
  }

  /// Returns `true` if the method chain should split if a split occurs inside
  /// [expression].
  ///
  /// In most cases, splitting in a method chain's target forces the chain to
  /// split too:
  ///
  ///      receiver(very, long, argument,
  ///              list)                    // <-- Split here...
  ///          .method();                   //     ...forces split here.
  ///
  /// However, if the target is a collection or function literal (or an
  /// argument list ending in one of those), we don't want to split:
  ///
  ///      receiver(inner(() {
  ///        ;
  ///      }).method();                     // <-- Unsplit.
  bool _forcesSplit(Expression expression) {
    // TODO(rnystrom): Other cases we may want to consider handling and
    // recursing into:
    // * ParenthesizedExpression.
    // * The right operand in an infix operator call.
    // * The body of a `=>` function.

    // Don't split right after a collection literal.
    if (expression is ListLiteral) return false;
    if (expression is MapLiteral) return false;

    // Don't split right after a non-empty curly-bodied function.
    if (expression is FunctionExpression) {
      if (expression.body is! BlockFunctionBody) return false;

      return (expression.body as BlockFunctionBody).block.statements.isEmpty;
    }

    // If the expression ends in an argument list, base the splitting on the
    // last argument.
    var argumentList;
    if (expression is MethodInvocation) {
      argumentList = expression.argumentList;
    } else if (expression is InstanceCreationExpression) {
      argumentList = expression.argumentList;
    } else if (expression is FunctionExpressionInvocation) {
      argumentList = expression.argumentList;
    }

    // Any other kind of expression always splits.
    if (argumentList == null) return true;
    if (argumentList.arguments.isEmpty) return true;

    var argument = argumentList.arguments.last;
    if (argument is NamedExpression) argument = argument.expression;

    // TODO(rnystrom): This logic is similar (but not identical) to
    // ArgumentListVisitor.hasBlockArguments. They overlap conceptually and
    // both have their own peculiar heuristics. It would be good to unify and
    // rationalize them.

    return _forcesSplit(argument);
  }

  /// Writes [call], which must be one of the supported expression types.
  void _writeCall(Expression call) {
    if (call is IndexExpression) {
      _visitor.builder.nestExpression();
      _writeCall(call.target);
      _visitor.finishIndexExpression(call);
      _visitor.builder.unnest();
    } else if (call is MethodInvocation) {
      _writeInvocation(call);
    } else if (call is PropertyAccess) {
      _visitor.token(call.operator);
      _visitor.visit(call.propertyName);
    } else if (call is PrefixedIdentifier) {
      _visitor.token(call.period);
      _visitor.visit(call.identifier);
    } else {
      // Unexpected type.
      assert(false);
    }
  }

  void _writeInvocation(MethodInvocation invocation) {
    _visitor.token(invocation.operator);
    _visitor.token(invocation.methodName.token);

    // If we don't have any block calls, stop the rule after the last method
    // call name, but before its arguments. This allows unsplit chains where
    // the last argument list wraps, like:
    //
    //     foo().bar().baz(
    //         argument, list);
    if (_blockCalls == null && _calls.isNotEmpty && invocation == _calls.last) {
      _disableRule();
    }

    // For a single method call on an identifier, stop the span before the
    // arguments to make it easier to keep the call name with the target. In
    // other words, prefer:
    //
    //     target.method(
    //         argument, list);
    //
    // Over:
    //
    //     target
    //         .method(argument, list);
    //
    // Alternatively, the way to think of this is try to avoid splitting on the
    // "." when calling a single method on a single name. This is especially
    // important because the identifier is often a library prefix, and splitting
    // there looks really odd.
    if (_properties.isEmpty &&
        _calls.length == 1 &&
        _blockCalls == null &&
        _target is SimpleIdentifier) {
      _endSpan();
    }

    _visitor.visit(invocation.argumentList);
  }

  void _writeBlockCall(MethodInvocation invocation) {
    _visitor.token(invocation.operator);
    _visitor.token(invocation.methodName.token);
    _visitor.visit(invocation.argumentList);
  }

  /// If a [Rule] for the method chain is currently active, ends it.
  void _disableRule() {
    if (_ruleEnabled == false) return;

    _visitor.builder.endRule();
    _ruleEnabled = false;
  }

  /// Creates a new method chain [Rule] if one is not already active.
  void _enableRule({bool lazy: false}) {
    if (_ruleEnabled) return;

    // If the properties split, force the calls to split too.
    var rule = new Rule();
    if (_propertyRule != null) _propertyRule.setNamedArgsRule(rule);

    if (lazy) {
      _visitor.builder.startLazyRule(rule);
    } else {
      _visitor.builder.startRule(rule);
    }

    _ruleEnabled = true;
  }

  /// Ends the span wrapping the call chain if it hasn't ended already.
  void _endSpan() {
    if (_spanEnded) return;

    _visitor.builder.endSpan();
    _spanEnded = true;
  }
}
