// Copyright (c) 2018, 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/status.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/search/element_visitors.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/utilities/flutter.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart' show SourceRange;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

/// [ExtractWidgetRefactoring] implementation.
class ExtractWidgetRefactoringImpl extends RefactoringImpl
    implements ExtractWidgetRefactoring {
  final SearchEngine searchEngine;
  final ResolvedUnitResult resolveResult;
  final AnalysisSessionHelper sessionHelper;
  final int offset;
  final int length;

  CorrectionUtils utils;

  ClassElement classBuildContext;
  ClassElement classKey;
  ClassElement classStatelessWidget;
  ClassElement classWidget;
  PropertyAccessorElement accessorRequired;

  @override
  String name;

  /// If [offset] is in a class, the node of this class, `null` otherwise.
  ClassDeclaration _enclosingClassNode;

  /// If [offset] is in a class, the element of this class, `null` otherwise.
  ClassElement _enclosingClassElement;

  /// The [CompilationUnitMember] that encloses the [offset].
  CompilationUnitMember _enclosingUnitMember;

  /// The widget creation expression to extract.
  InstanceCreationExpression _expression;

  /// The statements covered by [offset] and [length] to extract.
  List<Statement> _statements;

  /// The [SourceRange] that covers [_statements].
  SourceRange _statementsRange;

  /// The method returning widget to extract.
  MethodDeclaration _method;

  /// The parameters for the new widget class - referenced fields of the
  /// [_enclosingClassElement], local variables referenced by [_expression],
  /// and [_method] parameters.
  List<_Parameter> _parameters = [];

  ExtractWidgetRefactoringImpl(
      this.searchEngine, this.resolveResult, this.offset, this.length)
      : sessionHelper = new AnalysisSessionHelper(resolveResult.session) {
    utils = new CorrectionUtils(resolveResult);
  }

  @override
  String get refactoringName {
    return 'Extract Widget';
  }

  @override
  Future<RefactoringStatus> checkFinalConditions() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    RefactoringStatus result = new RefactoringStatus();
    result.addStatus(validateClassName(name));
    return result;
  }

  @override
  Future<RefactoringStatus> checkInitialConditions() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    RefactoringStatus result = new RefactoringStatus();

    result.addStatus(_checkSelection());
    if (result.hasFatalError) {
      return result;
    }

    AstNode astNode = _expression ?? _method ?? _statements.first;
    _enclosingUnitMember = astNode.thisOrAncestorMatching((n) {
      return n is CompilationUnitMember && n.parent is CompilationUnit;
    });

    result.addStatus(await _initializeClasses());
    result.addStatus(await _initializeParameters());

    return result;
  }

  @override
  RefactoringStatus checkName() {
    RefactoringStatus result = new RefactoringStatus();

    // Validate the name.
    result.addStatus(validateClassName(name));

    // Check for duplicate declarations.
    if (!result.hasFatalError) {
      visitLibraryTopLevelElements(resolveResult.libraryElement, (element) {
        if (hasDisplayName(element, name)) {
          String message = format(
              "Library already declares {0} with name '{1}'.",
              getElementKindName(element),
              name);
          result.addError(message, newLocation_fromElement(element));
        }
      });
    }

    return result;
  }

  @override
  Future<SourceChange> createChange() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    var changeBuilder = new DartChangeBuilder(sessionHelper.session);
    await changeBuilder.addFileEdit(resolveResult.path, (builder) {
      if (_expression != null) {
        builder.addReplacement(range.node(_expression), (builder) {
          _writeWidgetInstantiation(builder);
        });
      } else if (_statements != null) {
        builder.addReplacement(_statementsRange, (builder) {
          builder.write('return ');
          _writeWidgetInstantiation(builder);
          builder.write(';');
        });
      } else {
        _removeMethodDeclaration(builder);
        _replaceInvocationsWithInstantiations(builder);
      }

      _writeWidgetDeclaration(builder);
    });
    return changeBuilder.sourceChange;
  }

  @override
  bool isAvailable() {
    return !_checkSelection().hasFatalError;
  }

  /// Checks if [offset] is a widget creation expression that can be extracted.
  RefactoringStatus _checkSelection() {
    AstNode node = new NodeLocator(offset, offset + length)
        .searchWithin(resolveResult.unit);

    // Treat single ReturnStatement as its expression.
    if (node is ReturnStatement) {
      node = (node as ReturnStatement).expression;
    }

    // Find the enclosing class.
    _enclosingClassNode = node?.thisOrAncestorOfType<ClassDeclaration>();
    _enclosingClassElement = _enclosingClassNode?.declaredElement;

    // new MyWidget(...)
    InstanceCreationExpression newExpression = identifyNewExpression(node);
    if (isWidgetCreation(newExpression)) {
      _expression = newExpression;
      return new RefactoringStatus();
    }

    // Block with selected statements.
    if (node is Block) {
      var selectionRange = new SourceRange(offset, length);
      var statements = <Statement>[];
      for (var statement in node.statements) {
        var statementRange = range.node(statement);
        if (statementRange.intersects(selectionRange)) {
          statements.add(statement);
        }
      }
      if (statements.isNotEmpty) {
        var lastStatement = statements.last;
        if (lastStatement is ReturnStatement &&
            isWidgetExpression(lastStatement.expression)) {
          _statements = statements;
          _statementsRange = range.startEnd(statements.first, statements.last);
          return new RefactoringStatus();
        } else {
          return new RefactoringStatus.fatal(
              'The last selected statement must return a widget.');
        }
      }
    }

    // Widget myMethod(...) { ... }
    for (; node != null; node = node.parent) {
      if (node is FunctionBody) {
        break;
      }
      if (node is MethodDeclaration) {
        DartType returnType = node.returnType?.type;
        if (isWidgetType(returnType) && node.body != null) {
          _method = node;
          return new RefactoringStatus();
        }
        break;
      }
    }

    // Invalid selection.
    return new RefactoringStatus.fatal(
        'Can only extract a widget expression or a method returning widget.');
  }

  Future<RefactoringStatus> _initializeClasses() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    var result = new RefactoringStatus();

    Future<ClassElement> getClass(String name) async {
      // TODO(brianwilkerson) Determine whether this await is necessary.
      await null;
      const uri = 'package:flutter/widgets.dart';
      var element = await sessionHelper.getClass(uri, name);
      if (element == null) {
        result.addFatalError("Unable to find '$name' in $uri");
      }
      return element;
    }

    Future<PropertyAccessorElement> getAccessor(String uri, String name) async {
      // TODO(brianwilkerson) Determine whether this await is necessary.
      await null;
      var element = await sessionHelper.getTopLevelPropertyAccessor(uri, name);
      if (element == null) {
        result.addFatalError("Unable to find 'required' in $uri");
      }
      return element;
    }

    classBuildContext = await getClass('BuildContext');
    classKey = await getClass('Key');
    classStatelessWidget = await getClass('StatelessWidget');
    classWidget = await getClass('Widget');

    accessorRequired = await getAccessor('package:meta/meta.dart', 'required');

    return result;
  }

  /// Prepare referenced local variables and fields, that should be turned
  /// into the widget class fields and constructor parameters.
  Future<RefactoringStatus> _initializeParameters() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    _ParametersCollector collector;
    if (_expression != null) {
      SourceRange localRange = range.node(_expression);
      collector = new _ParametersCollector(_enclosingClassElement, localRange);
      _expression.accept(collector);
    }
    if (_statements != null) {
      collector =
          new _ParametersCollector(_enclosingClassElement, _statementsRange);
      for (var statement in _statements) {
        statement.accept(collector);
      }
    }
    if (_method != null) {
      SourceRange localRange = range.node(_method);
      collector = new _ParametersCollector(_enclosingClassElement, localRange);
      _method.body.accept(collector);
    }

    _parameters
      ..clear()
      ..addAll(collector.parameters);

    // We added fields, now add the method parameters.
    if (_method != null) {
      for (var parameter in _method.parameters.parameters) {
        if (parameter is DefaultFormalParameter) {
          DefaultFormalParameter defaultFormalParameter = parameter;
          parameter = defaultFormalParameter.parameter;
        }
        if (parameter is NormalFormalParameter) {
          _parameters.add(new _Parameter(
              parameter.identifier.name, parameter.declaredElement.type,
              isMethodParameter: true));
        }
      }
    }

    RefactoringStatus status = collector.status;

    // If there is an existing parameter "key" warn the user.
    // We could rename it, but that would require renaming references to it.
    // It is probably pretty rare, and the user can always rename before.
    for (var parameter in _parameters) {
      if (parameter.name == 'key') {
        status.addError(
            "The parameter 'key' will conflict with the widget 'key'.");
      }
    }

    // Collect used public names.
    var usedNames = new Set<String>();
    for (var parameter in _parameters) {
      if (!parameter.name.startsWith('_')) {
        usedNames.add(parameter.name);
      }
    }

    // Give each private parameter a public name for the constructor.
    for (var parameter in _parameters) {
      var name = parameter.name;
      if (name.startsWith('_')) {
        var baseName = name.substring(1);
        for (var i = 1;; i++) {
          name = i == 1 ? baseName : '$baseName$i';
          if (usedNames.add(name)) {
            break;
          }
        }
      }
      parameter.constructorName = name;
    }

    return collector.status;
  }

  /// Remove the [_method] declaration.
  void _removeMethodDeclaration(DartFileEditBuilder builder) {
    SourceRange methodRange = range.node(_method);
    SourceRange linesRange =
        utils.getLinesRange(methodRange, skipLeadingEmptyLines: true);
    builder.addDeletion(linesRange);
  }

  String _replaceIndent(String code, String indentOld, String indentNew) {
    var regExp = new RegExp('^$indentOld', multiLine: true);
    return code.replaceAll(regExp, indentNew);
  }

  /// Replace invocations of the [_method] with instantiations of the new
  /// widget class.
  void _replaceInvocationsWithInstantiations(DartFileEditBuilder builder) {
    var collector = new _MethodInvocationsCollector(_method.declaredElement);
    _enclosingClassNode.accept(collector);
    for (var invocation in collector.invocations) {
      List<Expression> arguments = invocation.argumentList.arguments;
      builder.addReplacement(range.node(invocation), (builder) {
        builder.write('new $name(');

        // Insert field references (as named arguments).
        // Ensure that invocation arguments are named.
        int argumentIndex = 0;
        for (var parameter in _parameters) {
          if (parameter != _parameters.first) {
            builder.write(', ');
          }
          builder.write(parameter.name);
          builder.write(': ');
          if (parameter.isMethodParameter) {
            Expression argument = arguments[argumentIndex++];
            if (argument is NamedExpression) {
              argument = (argument as NamedExpression).expression;
            }
            builder.write(utils.getNodeText(argument));
          } else {
            builder.write(parameter.name);
          }
        }
        builder.write(')');
      });
    }
  }

  /// Write declaration of the new widget class.
  void _writeWidgetDeclaration(DartFileEditBuilder builder) {
    builder.addInsertion(_enclosingUnitMember.end, (builder) {
      builder.writeln();
      builder.writeln();
      builder.writeClassDeclaration(
        name,
        superclass: classStatelessWidget.type,
        membersWriter: () {
          // Add the constructor.
          builder.write('  ');
          builder.writeConstructorDeclaration(
            name,
            isConst: true,
            parameterWriter: () {
              builder.writeln('{');

              // Add the required `key` parameter.
              builder.write('    ');
              builder.writeParameter('key', type: classKey.type);
              builder.writeln(',');

              // Add parameters for fields, local, and method parameters.
              for (var parameter in _parameters) {
                builder.write('    ');
                builder.write('@');
                builder.writeReference(accessorRequired);
                builder.write(' ');
                if (parameter.constructorName != parameter.name) {
                  builder.writeType(parameter.type);
                  builder.write(' ');
                  builder.write(parameter.constructorName);
                } else {
                  builder.write('this.');
                  builder.write(parameter.name);
                }
                builder.writeln(',');
              }

              builder.write('  }');
            },
            initializerWriter: () {
              for (var parameter in _parameters) {
                if (parameter.constructorName != parameter.name) {
                  builder.write(parameter.name);
                  builder.write(' = ');
                  builder.write(parameter.constructorName);
                  builder.write(', ');
                }
              }
              builder.write('super(key: key)');
            },
          );
          builder.writeln();
          builder.writeln();

          // Add the fields for the parameters.
          if (_parameters.isNotEmpty) {
            for (var parameter in _parameters) {
              builder.write('  ');
              builder.writeFieldDeclaration(parameter.name,
                  isFinal: true, type: parameter.type);
              builder.writeln();
            }
            builder.writeln();
          }

          // Widget build(BuildContext context) { ... }
          builder.writeln('  @override');
          builder.write('  ');
          builder.writeFunctionDeclaration(
            'build',
            returnType: classWidget.type,
            parameterWriter: () {
              builder.writeParameter('context', type: classBuildContext.type);
            },
            bodyWriter: () {
              if (_expression != null) {
                String indentOld = utils.getLinePrefix(_expression.offset);
                String indentNew = '    ';

                String code = utils.getNodeText(_expression);
                code = _replaceIndent(code, indentOld, indentNew);

                builder.writeln('{');

                builder.write('    return ');
                builder.write(code);
                builder.writeln(';');

                builder.writeln('  }');
              } else if (_statements != null) {
                String indentOld = utils.getLinePrefix(_statementsRange.offset);
                String indentNew = '    ';

                String code = utils.getRangeText(_statementsRange);
                code = _replaceIndent(code, indentOld, indentNew);

                builder.writeln('{');

                builder.write(indentNew);
                builder.write(code);
                builder.writeln();

                builder.writeln('  }');
              } else {
                String code = utils.getNodeText(_method.body);
                builder.writeln(code);
              }
            },
          );
        },
      );
    });
  }

  /// Write instantiation of the new widget class.
  void _writeWidgetInstantiation(DartEditBuilder builder) {
    builder.write('new $name(');

    for (var parameter in _parameters) {
      if (parameter != _parameters.first) {
        builder.write(', ');
      }
      builder.write(parameter.constructorName);
      builder.write(': ');
      builder.write(parameter.name);
    }

    builder.write(')');
  }
}

class _MethodInvocationsCollector extends RecursiveAstVisitor<void> {
  final MethodElement methodElement;
  final List<MethodInvocation> invocations = [];

  _MethodInvocationsCollector(this.methodElement);

  @override
  void visitMethodInvocation(MethodInvocation node) {
    if (node.methodName?.staticElement == methodElement) {
      invocations.add(node);
    } else {
      super.visitMethodInvocation(node);
    }
  }
}

class _Parameter {
  /// The name which is used to reference this parameter in the expression
  /// being extracted, and also the name of the field in the new widget.
  final String name;

  final DartType type;

  /// Whether the parameter is a parameter of the method being extracted.
  final bool isMethodParameter;

  /// If the [name] is private, the public name to use in the new widget
  /// constructor. If the [name] is already public, then the [name].
  String constructorName;

  _Parameter(this.name, this.type, {this.isMethodParameter: false});
}

class _ParametersCollector extends RecursiveAstVisitor<void> {
  final ClassElement enclosingClass;
  final SourceRange expressionRange;

  final RefactoringStatus status = new RefactoringStatus();
  final Set<Element> uniqueElements = new Set<Element>();
  final List<_Parameter> parameters = [];

  List<ClassElement> enclosingClasses;

  _ParametersCollector(this.enclosingClass, this.expressionRange);

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    Element element = node.staticElement;
    if (element == null) {
      return;
    }
    String elementName = element.displayName;

    DartType type;
    if (element is MethodElement) {
      if (_isMemberOfEnclosingClass(element)) {
        status.addError(
            "Reference to an enclosing class method cannot be extracted.");
      }
    } else if (element is LocalVariableElement) {
      if (!expressionRange.contains(element.nameOffset)) {
        if (node.inSetterContext()) {
          status.addError("Write to '$elementName' cannot be extracted.");
        } else {
          type = element.type;
        }
      }
    } else if (element is PropertyAccessorElement) {
      PropertyInducingElement field = element.variable;
      if (_isMemberOfEnclosingClass(field)) {
        if (node.inSetterContext()) {
          status.addError("Write to '$elementName' cannot be extracted.");
        } else {
          type = field.type;
        }
      }
    }
    // TODO(scheglov) support for ParameterElement

    if (type != null && uniqueElements.add(element)) {
      parameters.add(new _Parameter(elementName, type));
    }
  }

  /// Return `true` if the given [element] is a member of the [enclosingClass]
  /// or one of its supertypes, interfaces, or mixins.
  bool _isMemberOfEnclosingClass(Element element) {
    if (enclosingClass != null) {
      if (enclosingClasses == null) {
        enclosingClasses = <ClassElement>[]
          ..add(enclosingClass)
          ..addAll(enclosingClass.allSupertypes.map((t) => t.element));
      }
      return enclosingClasses.contains(element.enclosingElement);
    }
    return false;
  }
}
