// 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/analyzer.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/src/dart/analysis/session_helper.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 AnalysisSessionHelper sessionHelper;
  final CompilationUnit unit;
  final int offset;

  CompilationUnitElement unitElement;
  LibraryElement libraryElement;
  CorrectionUtils utils;

  ClassElement classBuildContext;
  ClassElement classKey;
  ClassElement classStatefulWidget;
  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 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, AnalysisSession session, this.unit, this.offset)
      : sessionHelper = new AnalysisSessionHelper(session) {
    unitElement = unit.element;
    libraryElement = unitElement.library;
    utils = new CorrectionUtils(unit);
  }

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

  @override
  Future<RefactoringStatus> checkFinalConditions() async {
    RefactoringStatus result = new RefactoringStatus();
    result.addStatus(validateClassName(name));
    return result;
  }

  @override
  Future<RefactoringStatus> checkInitialConditions() async {
    RefactoringStatus result = new RefactoringStatus();

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

    _enclosingUnitMember = (_expression ?? _method).getAncestor(
        (n) => 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(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 {
    String file = unitElement.source.fullName;
    var changeBuilder = new DartChangeBuilder(sessionHelper.session);
    await changeBuilder.addFileEdit(file, (builder) {
      if (_expression != null) {
        builder.addReplacement(range.node(_expression), (builder) {
          _writeWidgetInstantiation(builder);
        });
      } else {
        _removeMethodDeclaration(builder);
        _replaceInvocationsWithInstantiations(builder);
      }

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

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

  @override
  bool requiresPreview() => false;

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

    // Find the enclosing class.
    _enclosingClassNode = node?.getAncestor((n) => n is ClassDeclaration);
    _enclosingClassElement = _enclosingClassNode?.element;

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

    // 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 {
    var result = new RefactoringStatus();

    Future<ClassElement> getClass(String name) async {
      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 {
      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');
    classStatefulWidget = await getClass('StatefulWidget');
    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 {
    _ParametersCollector collector;
    if (_expression != null) {
      SourceRange localRange = range.node(_expression);
      collector = new _ParametersCollector(_enclosingClassElement, localRange);
      _expression.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.element.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);
  }

  /// Replace invocations of the [_method] with instantiations of the new
  /// widget class.
  void _replaceInvocationsWithInstantiations(DartFileEditBuilder builder) {
    var collector = new _MethodInvocationsCollector(_method.element);
    _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 = code.replaceAll(
                    new RegExp('^$indentOld', multiLine: true), indentNew);

                builder.writeln('{');

                builder.write('    return ');
                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;
        }
      }
    }

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