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

import 'dart:async';

import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart' as engine;
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

/**
 * An enumeration of possible postfix completion kinds.
 */
class DartPostfixCompletion {
  static const NO_TEMPLATE =
      const PostfixCompletionKind('', 'no change', null, null);
  static const ALL_TEMPLATES = const [
    const PostfixCompletionKind("assert", "expr.assert -> assert(expr);",
        isAssertContext, expandAssert),
    const PostfixCompletionKind(
        "fori",
        "limit.fori -> for(var i = 0; i < limit; i++) {}",
        isIntContext,
        expandFori),
    const PostfixCompletionKind(
        "for",
        "values.for -> for(var value in values) {}",
        isIterableContext,
        expandFor),
    const PostfixCompletionKind(
        "iter",
        "values.iter -> for(var value in values) {}",
        isIterableContext,
        expandFor),
    const PostfixCompletionKind(
        "not", "bool.not -> !bool", isBoolContext, expandNegate),
    const PostfixCompletionKind(
        "!", "bool! -> !bool", isBoolContext, expandNegate),
    const PostfixCompletionKind(
        "else", "bool.else -> if (!bool) {}", isBoolContext, expandElse),
    const PostfixCompletionKind(
        "if", "bool.if -> if (bool) {}", isBoolContext, expandIf),
    const PostfixCompletionKind("nn", "expr.nn -> if (expr != null) {}",
        isObjectContext, expandNotNull),
    const PostfixCompletionKind("notnull",
        "expr.notnull -> if (expr != null) {}", isObjectContext, expandNotNull),
    const PostfixCompletionKind("null", "expr.null -> if (expr == null) {}",
        isObjectContext, expandNull),
    const PostfixCompletionKind(
        "par", "expr.par -> (expr)", isObjectContext, expandParen),
    const PostfixCompletionKind(
        "return", "expr.return -> return expr", isObjectContext, expandReturn),
    const PostfixCompletionKind("switch", "expr.switch -> switch (expr) {}",
        isSwitchContext, expandSwitch),
    const PostfixCompletionKind("try", "stmt.try -> try {stmt} catch (e,s) {}",
        isStatementContext, expandTry),
    const PostfixCompletionKind(
        "tryon",
        "stmt.try -> try {stmt} on Exception catch (e,s) {}",
        isStatementContext,
        expandTryon),
    const PostfixCompletionKind(
        "while", "expr.while -> while (expr) {}", isBoolContext, expandWhile),
  ];

  static Future<PostfixCompletion> expandAssert(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findAssertExpression, (expr) {
      return "assert(${processor.utils.getNodeText(expr)});";
    }, withBraces: false);
  }

  static Future<PostfixCompletion> expandElse(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findBoolExpression,
        (expr) => "if (${processor.makeNegatedBoolExpr(expr)})");
  }

  static Future<PostfixCompletion> expandFor(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findIterableExpression, (expr) {
      String value = processor.newVariable("value");
      return "for (var $value in ${processor.utils.getNodeText(expr)})";
    });
  }

  static Future<PostfixCompletion> expandFori(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findIntExpression, (expr) {
      String index = processor.newVariable("i");
      return "for (int $index = 0; $index < ${processor.utils.getNodeText(expr)}; $index++)";
    });
  }

  static Future<PostfixCompletion> expandIf(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findBoolExpression,
        (expr) => "if (${processor.utils.getNodeText(expr)})");
  }

  static Future<PostfixCompletion> expandNegate(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findBoolExpression,
        (expr) => processor.makeNegatedBoolExpr(expr),
        withBraces: false);
  }

  static Future<PostfixCompletion> expandNotNull(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findObjectExpression, (expr) {
      return expr is NullLiteral
          ? "if (false)"
          : "if (${processor.utils.getNodeText(expr)} != null)";
    });
  }

  static Future<PostfixCompletion> expandNull(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findObjectExpression, (expr) {
      return expr is NullLiteral
          ? "if (true)"
          : "if (${processor.utils.getNodeText(expr)} == null)";
    });
  }

  static Future<PostfixCompletion> expandParen(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findObjectExpression,
        (expr) => "(${processor.utils.getNodeText(expr)})",
        withBraces: false);
  }

  static Future<PostfixCompletion> expandReturn(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findObjectExpression,
        (expr) => "return ${processor.utils.getNodeText(expr)};",
        withBraces: false);
  }

  static Future<PostfixCompletion> expandSwitch(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findObjectExpression,
        (expr) => "switch (${processor.utils.getNodeText(expr)})");
  }

  static Future<PostfixCompletion> expandTry(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expandTry(kind, processor.findStatement, withOn: false);
  }

  static Future<PostfixCompletion> expandTryon(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expandTry(kind, processor.findStatement, withOn: true);
  }

  static Future<PostfixCompletion> expandWhile(
      PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return processor.expand(kind, processor.findBoolExpression,
        (expr) => "while (${processor.utils.getNodeText(expr)})");
  }

  static PostfixCompletionKind forKey(String key) =>
      ALL_TEMPLATES.firstWhere((kind) => kind.key == key, orElse: () => null);

  static bool isAssertContext(PostfixCompletionProcessor processor) {
    return processor.findAssertExpression() != null;
  }

  static bool isBoolContext(PostfixCompletionProcessor processor) {
    return processor.findBoolExpression() != null;
  }

  static bool isIntContext(PostfixCompletionProcessor processor) {
    return processor.findIntExpression() != null;
  }

  static bool isIterableContext(PostfixCompletionProcessor processor) {
    return processor.findIterableExpression() != null;
  }

  static bool isObjectContext(PostfixCompletionProcessor processor) {
    return processor.findObjectExpression() != null;
  }

  static bool isStatementContext(PostfixCompletionProcessor processor) {
    return processor.findStatement() != null;
  }

  static bool isSwitchContext(PostfixCompletionProcessor processor) {
    return processor.findObjectExpression() != null;
  }
}

/**
 * A description of a postfix completion.
 *
 * Clients may not extend, implement or mix-in this class.
 */
class PostfixCompletion {
  /**
   * A description of the assist being proposed.
   */
  final PostfixCompletionKind kind;

  /**
   * The change to be made in order to apply the assist.
   */
  final SourceChange change;

  /**
   * Initialize a newly created completion to have the given [kind] and [change].
   */
  PostfixCompletion(this.kind, this.change);
}

/**
 * The context for computing a postfix completion.
 */
class PostfixCompletionContext {
  final String file;
  final LineInfo lineInfo;
  final int selectionOffset;
  final String key;
  final AnalysisDriver driver;
  final CompilationUnit unit;
  final CompilationUnitElement unitElement;
  final List<engine.AnalysisError> errors;

  PostfixCompletionContext(this.file, this.lineInfo, this.selectionOffset,
      this.key, this.driver, this.unit, this.unitElement, this.errors) {
    if (unitElement.context == null) {
      throw new Error(); // not reached
    }
  }
}

/**
 * A description of a template for postfix completion. Instances are intended to
 * hold the functions required to determine applicability and expand the
 * template, in addition to its name and simple example. The example is shown
 * (in IntelliJ) in a code-completion menu, so must be quite short.
 *
 * Clients may not extend, implement or mix-in this class.
 */
class PostfixCompletionKind {
  final String name, example;
  final Function selector;
  final Function computer;

  const PostfixCompletionKind(
      this.name, this.example, this.selector, this.computer);

  String get key => name == '!' ? name : '.$name';

  String get message => 'Expand $key';

  @override
  String toString() => name;
}

/**
 * The computer for Dart postfix completions.
 */
class PostfixCompletionProcessor {
  static final NO_COMPLETION = new PostfixCompletion(
      DartPostfixCompletion.NO_TEMPLATE, new SourceChange("", edits: []));

  final PostfixCompletionContext completionContext;
  final CorrectionUtils utils;
  AstNode node;
  PostfixCompletion completion;
  SourceChange change = new SourceChange('postfix-completion');
  final Map<String, LinkedEditGroup> linkedPositionGroups =
      <String, LinkedEditGroup>{};
  Position exitPosition = null;
  TypeProvider _typeProvider;

  PostfixCompletionProcessor(this.completionContext)
      : utils = new CorrectionUtils(completionContext.unit);

  AnalysisDriver get driver => completionContext.driver;

  String get eol => utils.endOfLine;

  String get file => completionContext.file;

  String get key => completionContext.key;

  LineInfo get lineInfo => completionContext.lineInfo;

  int get requestLine => lineInfo.getLocation(selectionOffset).lineNumber;

  int get selectionOffset => completionContext.selectionOffset;

  /**
   * Return the analysis session to be used to create the change builder.
   */
  AnalysisSession get session => driver.currentSession;

  Source get source => completionContext.unitElement.source;

  TypeProvider get typeProvider {
    return _typeProvider ??= unitElement.context.typeProvider;
  }

  CompilationUnit get unit => completionContext.unit;

  CompilationUnitElement get unitElement => completionContext.unitElement;

  Future<PostfixCompletion> compute() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    node = _selectedNode();
    if (node == null) {
      return NO_COMPLETION;
    }
    PostfixCompletionKind completer = DartPostfixCompletion.forKey(key);
    return completer?.computer(this, completer) ?? NO_COMPLETION;
  }

  Future<PostfixCompletion> expand(
      PostfixCompletionKind kind, Function contexter, Function sourcer,
      {bool withBraces: true}) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    AstNode expr = contexter();
    if (expr == null) {
      return null;
    }

    DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
      builder.addReplacement(range.node(expr), (DartEditBuilder builder) {
        String newSrc = sourcer(expr);
        if (newSrc == null) {
          return null;
        }
        builder.write(newSrc);
        if (withBraces) {
          builder.write(" {");
          builder.write(eol);
          String indent = utils.getNodePrefix(expr);
          builder.write(indent);
          builder.write(utils.getIndent(1));
          builder.selectHere();
          builder.write(eol);
          builder.write(indent);
          builder.write("}");
        } else {
          builder.selectHere();
        }
      });
    });
    _setCompletionFromBuilder(changeBuilder, kind);
    return completion;
  }

  Future<PostfixCompletion> expandTry(
      PostfixCompletionKind kind, Function contexter,
      {bool withOn: false}) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    AstNode stmt = contexter();
    if (stmt == null) {
      return null;
    }
    DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
      // Embed the full line(s) of the statement in the try block.
      var startLine = lineInfo.getLocation(stmt.offset).lineNumber - 1;
      var endLine = lineInfo.getLocation(stmt.end).lineNumber - 1;
      if (stmt is ExpressionStatement && !stmt.semicolon.isSynthetic) {
        endLine += 1;
      }
      var startOffset = lineInfo.getOffsetOfLine(startLine);
      var endOffset = lineInfo.getOffsetOfLine(endLine);
      var src = utils.getText(startOffset, endOffset - startOffset);
      String indent = utils.getLinePrefix(stmt.offset);
      builder.addReplacement(range.startOffsetEndOffset(startOffset, endOffset),
          (DartEditBuilder builder) {
        builder.write(indent);
        builder.write('try {');
        builder.write(eol);
        builder.write(src.replaceAll(new RegExp("^$indent", multiLine: true),
            "$indent${utils.getIndent(1)}"));
        builder.selectHere();
        builder.write(indent);
        builder.write('}');
        if (withOn) {
          builder.write(' on ');
          builder.addSimpleLinkedEdit('NAME', nameOfExceptionThrownBy(stmt));
        }
        builder.write(' catch (e, s) {');
        builder.write(eol);
        builder.write(indent);
        builder.write(utils.getIndent(1));
        builder.write('print(s);');
        builder.write(eol);
        builder.write(indent);
        builder.write("}");
        builder.write(eol);
      });
    });
    _setCompletionFromBuilder(changeBuilder, kind);
    return completion;
  }

  Expression findAssertExpression() {
    if (node is Expression) {
      Expression boolExpr = _findOuterExpression(node, typeProvider.boolType);
      if (boolExpr == null) {
        return null;
      }
      if (boolExpr.parent is ExpressionFunctionBody &&
          boolExpr.parent.parent is FunctionExpression) {
        FunctionExpression fnExpr = boolExpr.parent.parent;
        var type = fnExpr.staticType;
        if (type is! FunctionType) {
          return boolExpr;
        }
        FunctionType fnType = type;
        if (fnType.returnType == typeProvider.boolType) {
          return fnExpr;
        }
      }
      if (boolExpr.staticType == typeProvider.boolType) {
        return boolExpr;
      }
    }
    return null;
  }

  Expression findBoolExpression() =>
      _findOuterExpression(node, typeProvider.boolType);

  Expression findIntExpression() =>
      _findOuterExpression(node, typeProvider.intType);

  Expression findIterableExpression() =>
      _findOuterExpression(node, typeProvider.iterableType);

  Expression findObjectExpression() =>
      _findOuterExpression(node, typeProvider.objectType);

  AstNode findStatement() {
    var astNode = node;
    while (astNode != null) {
      if (astNode is Statement && astNode is! Block) {
        // Disallow control-flow statements.
        if (astNode is DoStatement ||
            astNode is IfStatement ||
            astNode is ForEachStatement ||
            astNode is ForStatement ||
            astNode is SwitchStatement ||
            astNode is TryStatement ||
            astNode is WhileStatement) {
          return null;
        }
        return astNode;
      }
      astNode = astNode.parent;
    }
    return null;
  }

  Future<bool> isApplicable() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    node = _selectedNode();
    if (node == null) {
      return false;
    }
    PostfixCompletionKind completer = DartPostfixCompletion.forKey(key);
    return completer?.selector(this);
  }

  String makeNegatedBoolExpr(Expression expr) {
    String originalSrc = utils.getNodeText(expr);
    String newSrc = utils.invertCondition(expr);
    if (newSrc != originalSrc) {
      return newSrc;
    } else {
      return "!${utils.getNodeText(expr)}";
    }
  }

  String nameOfExceptionThrownBy(AstNode astNode) {
    if (astNode is ExpressionStatement) {
      astNode = (astNode as ExpressionStatement).expression;
    }
    if (astNode is ThrowExpression) {
      ThrowExpression expr = astNode;
      var type = expr.expression.staticType;
      return type.displayName;
    }
    return 'Exception';
  }

  String newVariable(String base) {
    String name = base;
    int i = 1;
    Set<String> vars =
        utils.findPossibleLocalVariableConflicts(selectionOffset);
    while (vars.contains(name)) {
      name = "$base${i++}";
    }
    return name;
  }

  Expression _findOuterExpression(AstNode start, InterfaceType builtInType) {
    if (start is SimpleIdentifier && start.staticElement is PrefixElement) {
      return null;
    }

    AstNode parent;
    if (start is Expression) {
      parent = start;
    } else if (start is ArgumentList) {
      parent = start.parent;
    }
    if (parent == null) {
      return null;
    }

    var list = <Expression>[];
    while (parent is Expression) {
      list.add(parent);
      parent = parent.parent;
    }

    Expression expr = list.firstWhere((expr) {
      DartType type = expr.staticType;
      if (type == null) return false;
      if (type.isSubtypeOf(builtInType)) return true;
      Element element = type.element;
      if (element is TypeDefiningElement) {
        TypeDefiningElement typeDefElem = element;
        type = typeDefElem.type;
        if (type is ParameterizedType) {
          ParameterizedType pType = type;
          type = pType.instantiate(new List.filled(
              pType.typeParameters.length, typeProvider.dynamicType));
        }
      }
      return type.isSubtypeOf(builtInType);
    }, orElse: () => null);
    if (expr is SimpleIdentifier && expr.parent is PropertyAccess) {
      expr = expr.parent;
    }
    if (expr?.parent is CascadeExpression) {
      expr = expr.parent;
    }
    return expr;
  }

  AstNode _selectedNode({int at: null}) =>
      new NodeLocator(at == null ? selectionOffset : at).searchWithin(unit);

  void _setCompletionFromBuilder(
      DartChangeBuilder builder, PostfixCompletionKind kind,
      [List args]) {
    SourceChange change = builder.sourceChange;
    if (change.edits.isEmpty) {
      completion = null;
      return;
    }
    change.message = formatList(kind.message, args);
    completion = new PostfixCompletion(kind, change);
  }
}
