// 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.

import 'dart:async';

import 'package:analysis_server/plugin/protocol/protocol.dart' hide ElementKind;
import 'package:analysis_server/src/provisional/edit/utilities/change_builder_core.dart';
import 'package:analysis_server/src/provisional/edit/utilities/change_builder_dart.dart';
import 'package:analysis_server/src/services/correction/name_suggestion.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/utilities/change_builder_core.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';

/**
 * A [ChangeBuilder] used to build changes in Dart files.
 */
class DartChangeBuilderImpl extends ChangeBuilderImpl
    implements DartChangeBuilder {
  /**
   * The analysis driver in which the files being edited were analyzed.
   */
  final AnalysisDriver driver;

  /**
   * Initialize a newly created change builder.
   */
  DartChangeBuilderImpl(this.driver);

  @override
  Future<DartFileEditBuilderImpl> createFileEditBuilder(
      String path, int fileStamp) async {
    AnalysisResult result = await driver.getResult(path);
    return new DartFileEditBuilderImpl(this, path, fileStamp, result.unit);
  }
}

/**
 * An [EditBuilder] used to build edits in Dart files.
 */
class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
  /**
   * A utility class used to help build the source code.
   */
  final CorrectionUtils utils;

  /**
   * Initialize a newly created builder to build a source edit.
   */
  DartEditBuilderImpl(
      DartFileEditBuilderImpl sourceFileEditBuilder, int offset, int length)
      : utils = sourceFileEditBuilder.utils,
        super(sourceFileEditBuilder, offset, length);

  DartFileEditBuilderImpl get dartFileEditBuilder => fileEditBuilder;

  @override
  void writeClassDeclaration(String name,
      {Iterable<DartType> interfaces,
      bool isAbstract: false,
      void memberWriter(),
      Iterable<DartType> mixins,
      String nameGroupName,
      DartType superclass}) {
    // TODO(brianwilkerson) Add support for type parameters, probably as a
    // parameterWriter parameter.
    // TODO(brianwilkerson) Add a superclassGroupName parameter.
    if (isAbstract) {
      write(Keyword.ABSTRACT.syntax);
      write(' ');
    }
    write('class ');
    if (nameGroupName == null) {
      write(name);
    } else {
      addLinkedEdit(DartEditBuilder.NAME_GROUP_ID, (LinkedEditBuilder builder) {
        write(name);
      });
    }
    if (superclass != null) {
      write(' extends ');
      writeType(superclass, groupName: DartEditBuilder.SUPERCLASS_GROUP_ID);
    } else if (mixins != null && mixins.isNotEmpty) {
      write(' extends Object ');
    }
    writeTypes(mixins, prefix: ' with ');
    writeTypes(interfaces, prefix: ' implements ');
    writeln(' {');
    if (memberWriter != null) {
      writeln();
      memberWriter();
      writeln();
    }
    write('}');
  }

  //@override
  void writeConstructorDeclaration(ClassElement classElement,
      {ArgumentList argumentList,
      SimpleIdentifier constructorName,
      bool isConst: false}) {
    // TODO(brianwilkerson) Clean up the API and add it to the public API.
    //
    // TODO(brianwilkerson) Support passing a list of final fields rather than
    // an argument list.
    if (isConst) {
      write(Keyword.CONST.syntax);
      write(' ');
    }
    write(classElement.name);
    write('.');
    if (constructorName != null) {
      addLinkedEdit(DartEditBuilder.NAME_GROUP_ID, (LinkedEditBuilder builder) {
        write(constructorName.name);
      });
      CompilationUnit unit = constructorName
          .getAncestor((AstNode node) => node is CompilationUnit);
      if (unit != null) {
        CompilationUnitElement element = unit.element;
        if (element != null) {
          String referenceFile = element.source.fullName;
          if (referenceFile == dartFileEditBuilder.fileEdit.file) {
            dartFileEditBuilder.addLinkedPosition(constructorName.offset,
                constructorName.length, DartEditBuilder.NAME_GROUP_ID);
          }
        }
      }
    }
    if (argumentList != null) {
      writeParametersMatchingArguments(argumentList);
    } else {
      write('()');
    }
    writeln(' {');
    write('  }');
  }

  @override
  void writeFieldDeclaration(String name,
      {void initializerWriter(),
      bool isConst: false,
      bool isFinal: false,
      bool isStatic: false,
      String nameGroupName,
      DartType type,
      String typeGroupName}) {
    if (isStatic) {
      write(Keyword.STATIC.syntax);
      write(' ');
    }
    bool typeRequired = true;
    if (isConst) {
      write(Keyword.CONST.syntax);
      typeRequired = false;
    } else if (isFinal) {
      write(Keyword.FINAL.syntax);
      typeRequired = false;
    }
    if (type != null) {
      writeType(type, groupName: typeGroupName);
    } else if (typeRequired) {
      write(Keyword.VAR.syntax);
    }
    write(' ');
    if (nameGroupName != null) {
      addLinkedEdit(nameGroupName, (LinkedEditBuilder builder) {
        write(name);
      });
    } else {
      write(name);
    }
    if (initializerWriter != null) {
      write(' = ');
      initializerWriter();
    }
    write(';');
  }

  @override
  void writeGetterDeclaration(String name,
      {void bodyWriter(),
      bool isStatic: false,
      String nameGroupName,
      DartType returnType,
      String returnTypeGroupName}) {
    if (isStatic) {
      write(Keyword.STATIC.syntax);
      write(' ');
    }
    if (returnType != null) {
      writeType(returnType, groupName: returnTypeGroupName);
      write(' ');
    }
    write(Keyword.GET.syntax);
    write(' ');
    if (nameGroupName != null) {
      addLinkedEdit(nameGroupName, (LinkedEditBuilder builder) {
        write(name);
      });
    } else {
      write(name);
    }
    if (bodyWriter == null) {
      write(' => null;');
    } else {
      write(' ');
      bodyWriter();
    }
  }

  @override
  void writeOverrideOfInheritedMember(ExecutableElement member) {
    // prepare environment
    String prefix = utils.getIndent(1);
    // may be property
    String prefix2 = utils.getIndent(2);
    ElementKind elementKind = member.kind;
    bool isGetter = elementKind == ElementKind.GETTER;
    bool isSetter = elementKind == ElementKind.SETTER;
    bool isMethod = elementKind == ElementKind.METHOD;
    bool isOperator = isMethod && (member as MethodElement).isOperator;
    write(prefix);
    if (isGetter) {
      writeln('// TODO: implement ${member.displayName}');
      write(prefix);
    }
    // @override
    writeln('@override');
    write(prefix);
    // return type
    // REVIEW: Added groupId
    bool shouldReturn = writeType(member.type.returnType,
        groupName: DartEditBuilder.RETURN_TYPE_GROUP_ID);
    write(' ');
    if (isGetter) {
      write(Keyword.GET.syntax);
      write(' ');
    } else if (isSetter) {
      write(Keyword.SET.syntax);
      write(' ');
    } else if (isOperator) {
      write(Keyword.OPERATOR.syntax);
      write(' ');
    }
    // name
    write(member.displayName);
    // parameters + body
    if (isGetter) {
      writeln(' => null;');
    } else {
      List<ParameterElement> parameters = member.parameters;
      writeParameters(parameters);
      writeln(' {');
      // TO-DO
      write(prefix2);
      writeln('// TODO: implement ${member.displayName}');
      // REVIEW: Added return statement.
      if (shouldReturn) {
        write(prefix2);
        writeln('return null;');
      }
      // close method
      write(prefix);
      writeln('}');
    }
  }

  @override
  void writeParameters(Iterable<ParameterElement> parameters) {
    write('(');
    bool sawNamed = false;
    bool sawPositional = false;
    for (int i = 0; i < parameters.length; i++) {
      ParameterElement parameter = parameters.elementAt(i);
      if (i > 0) {
        write(', ');
      }
      // may be optional
      ParameterKind parameterKind = parameter.parameterKind;
      if (parameterKind == ParameterKind.NAMED) {
        if (!sawNamed) {
          write('{');
          sawNamed = true;
        }
      }
      if (parameterKind == ParameterKind.POSITIONAL) {
        if (!sawPositional) {
          write('[');
          sawPositional = true;
        }
      }
      // parameter
      writeParameterSource(parameter.type, parameter.name);
      // default value
      String defaultCode = parameter.defaultValueCode;
      if (defaultCode != null) {
        if (sawPositional) {
          write(' = ');
        } else {
          write(': ');
        }
        write(defaultCode);
      }
    }
    // close parameters
    if (sawNamed) {
      write('}');
    }
    if (sawPositional) {
      write(']');
    }
    write(')');
  }

  @override
  void writeParametersMatchingArguments(ArgumentList arguments) {
    Set<String> excluded = new Set();
    bool namedFound = false;
    write('(');
    List<Expression> argumentList = arguments.arguments;
    for (int i = 0; i < argumentList.length; i++) {
      Expression argument = argumentList[i];
      DartType type = argument.bestType;
      List<String> suggestions =
          _getParameterNameSuggestions(excluded, type, argument, i);
      String favorite = suggestions[0];
      // append separator
      if (i > 0) {
        write(', ');
      }
      if (argument is NamedExpression) {
        if (!namedFound) {
          namedFound = true;
          write('[');
        }
        favorite = argument.name.label.name;
      }
      // append type name
      writeType(type, addSupertypeProposals: true, groupName: 'TYPE$i');
      write(' ');
      // append parameter name
      excluded.add(favorite);
      addLinkedEdit('ARG$i', (LinkedEditBuilder builder) {
        builder.write(favorite);
        builder.addSuggestions(LinkedEditSuggestionKind.PARAMETER, suggestions);
      });
    }
    if (namedFound) {
      write(']');
    }
    write(')');
  }

  @override
  void writeParameterSource(DartType type, String name) {
    String parameterSource = utils.getParameterSource(
        type, name, dartFileEditBuilder.librariesToImport);
    write(parameterSource);
  }

  @override
  bool writeType(DartType type,
      {bool addSupertypeProposals: false,
      String groupName,
      bool required: false}) {
    if (type != null && !type.isDynamic) {
      String typeSource =
          utils.getTypeSource(type, dartFileEditBuilder.librariesToImport);
      if (groupName != null) {
        addLinkedEdit(groupName, (LinkedEditBuilder builder) {
          write(typeSource);
          if (addSupertypeProposals) {
            _addSuperTypeProposals(builder, type, new Set<DartType>());
          }
        });
      } else {
        write(typeSource);
      }
      return true;
    } else if (required) {
      write(Keyword.VAR.syntax);
    }
    return false;
  }

  /**
   * Write the code for a comma-separated list of [types], optionally prefixed
   * by a [prefix]. If the list of [types] is `null` or does not return any
   * types, then nothing will be written.
   */
  void writeTypes(Iterable<DartType> types, {String prefix}) {
    if (types == null || types.isEmpty) {
      return;
    }
    bool first = true;
    for (DartType type in types) {
      if (first) {
        if (prefix != null) {
          write(prefix);
        }
        first = false;
      } else {
        write(', ');
      }
      writeType(type);
    }
  }

  void _addSuperTypeProposals(
      LinkedEditBuilder builder, DartType type, Set<DartType> alreadyAdded) {
    if (type != null &&
        type.element is ClassElement &&
        alreadyAdded.add(type)) {
      ClassElement element = type.element as ClassElement;
      builder.addSuggestion(LinkedEditSuggestionKind.TYPE, element.name);
      _addSuperTypeProposals(builder, element.supertype, alreadyAdded);
      for (InterfaceType interfaceType in element.interfaces) {
        _addSuperTypeProposals(builder, interfaceType, alreadyAdded);
      }
    }
  }

  /**
   * Return a list containing the suggested names for a parmeter with the given
   * [type] whose value in one location is computed by the given [expression].
   * The list will not contain any names in the set of [excluded] names. The
   * [index] is the index of the argument, used to create a name if no better
   * name could be created. The first name in the list will be the best name.
   */
  List<String> _getParameterNameSuggestions(
      Set<String> excluded, DartType type, Expression expression, int index) {
    List<String> suggestions =
        getVariableNameSuggestionsForExpression(type, expression, excluded);
    if (suggestions.length != 0) {
      return suggestions;
    }
    return <String>['arg$index'];
  }
}

/**
 * A [FileEditBuilder] used to build edits for Dart files.
 */
class DartFileEditBuilderImpl extends FileEditBuilderImpl
    implements DartFileEditBuilder {
  /**
   * The compilation unit to which the code will be added.
   */
  CompilationUnit unit;

  /**
   * A utility class used to help build the source code.
   */
  CorrectionUtils utils;

  /**
   * A set containing the sources of the libraries that need to be imported in
   * order to make visible the names used in generated code.
   */
  Set<Source> librariesToImport = new Set<Source>();

  /**
   * Initialize a newly created builder to build a source file edit within the
   * change being built by the given [changeBuilder]. The file being edited has
   * the given [source] and [timeStamp], and the given fully resolved [unit].
   */
  DartFileEditBuilderImpl(DartChangeBuilderImpl changeBuilder, String path,
      int timeStamp, this.unit)
      : super(changeBuilder, path, timeStamp) {
    utils = new CorrectionUtils(unit);
  }

  @override
  DartEditBuilderImpl createEditBuilder(int offset, int length) {
    return new DartEditBuilderImpl(this, offset, length);
  }
}
