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

library analysis_server.src.utilities.change_builder_dart;

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/generated/engine.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 context in which the files being edited were analyzed.
   */
  final AnalysisContext context;

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

  @override
  DartFileEditBuilderImpl createFileEditBuilder(Source source, int fileStamp) {
    return new DartFileEditBuilderImpl(this, source, fileStamp);
  }
}

/**
 * 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].
   */
  DartFileEditBuilderImpl(
      DartChangeBuilderImpl changeBuilder, Source source, int timeStamp)
      : super(changeBuilder, source, timeStamp) {
    AnalysisContext context = changeBuilder.context;
    List<Source> librariesContaining = context.getLibrariesContaining(source);
    if (librariesContaining.length < 1) {
      throw new StateError('Cannot build edits for ${source.fullName}');
    }
    unit = context.resolveCompilationUnit2(source, librariesContaining[0]);
    utils = new CorrectionUtils(unit);
  }

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