// Copyright (c) 2016, 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';

/**
 * [SdkPatcher] applies patches to SDK [CompilationUnit].
 */
class SdkPatcher {
  bool _allowNewPublicNames;
  String _baseDesc;
  String _patchDesc;
  CompilationUnit _patchUnit;

  /**
   * Patch the given [unit] of a SDK [source] with the patches defined in
   * [allPatchPaths].  Throw [ArgumentError] if a patch
   * file cannot be read, or the contents violates rules for patch files.
   */
  void patch(
      ResourceProvider resourceProvider,
      Map<String, List<String>> allPatchPaths,
      AnalysisErrorListener errorListener,
      Source source,
      CompilationUnit unit) {
    // Process URI.
    String libraryUriStr;
    bool isLibraryDefiningUnit;
    {
      Uri uri = source.uri;
      if (uri.scheme != 'dart') {
        throw new ArgumentError(
            'The URI of the unit to patch must have the "dart" scheme: $uri');
      }
      List<String> uriSegments = uri.pathSegments;
      String libraryName = uriSegments.first;
      libraryUriStr = 'dart:$libraryName';
      isLibraryDefiningUnit = uriSegments.length == 1;
      _allowNewPublicNames = libraryName == '_internal';
    }
    // Prepare the patch files to apply.
    List<String> patchPaths = allPatchPaths[libraryUriStr] ?? const <String>[];

    for (String path in patchPaths) {
      File patchFile = resourceProvider.getFile(path);
      if (!patchFile.exists) {
        throw new ArgumentError(
            'The patch file ${patchFile.path} for $source does not exist.');
      }
      Source patchSource = patchFile.createSource();
      CompilationUnit patchUnit = parse(patchSource, errorListener);

      // Prepare for reporting errors.
      _baseDesc = source.toString();
      _patchDesc = patchFile.path;
      _patchUnit = patchUnit;

      if (isLibraryDefiningUnit) {
        _patchDirectives(source, unit, patchSource, patchUnit);
      }
      _patchTopLevelDeclarations(unit, patchUnit, isLibraryDefiningUnit);
    }
  }

  void _failExternalKeyword(String name, int offset) {
    throw new ArgumentError(
        'The keyword "external" was expected for "$name" in $_baseDesc @ $offset.');
  }

  void _failIfPublicName(AstNode node, String name) {
    if (_allowNewPublicNames) {
      return;
    }
    if (!Identifier.isPrivateName(name)) {
      _failInPatch('contains a public declaration "$name"', node.offset);
    }
  }

  void _failInPatch(String message, int offset) {
    String loc = _getLocationDesc3(_patchUnit, offset);
    throw new ArgumentError(
        'The patch file $_patchDesc for $_baseDesc $message at $loc.');
  }

  String _getLocationDesc3(CompilationUnit unit, int offset) {
    CharacterLocation location = unit.lineInfo.getLocation(offset);
    return 'the line ${location.lineNumber}';
  }

  void _matchParameterLists(FormalParameterList baseParameters,
      FormalParameterList patchParameters, String context()) {
    if (baseParameters == null && patchParameters == null) return;
    if (baseParameters == null || patchParameters == null) {
      throw new ArgumentError("${context()}, parameter lists don't match");
    }
    if (baseParameters.parameters.length != patchParameters.parameters.length) {
      throw new ArgumentError(
          '${context()}, parameter lists have different lengths');
    }
    for (var i = 0; i < baseParameters.parameters.length; i++) {
      _matchParameters(baseParameters.parameters[i],
          patchParameters.parameters[i], () => '${context()}, parameter $i');
    }
  }

  void _matchParameters(FormalParameter baseParameter,
      FormalParameter patchParameter, String whichParameter()) {
    if (baseParameter.identifier.name != patchParameter.identifier.name) {
      throw new ArgumentError('${whichParameter()} has different name');
    }
    NormalFormalParameter baseParameterWithoutDefault =
        _withoutDefault(baseParameter);
    NormalFormalParameter patchParameterWithoutDefault =
        _withoutDefault(patchParameter);
    if (baseParameterWithoutDefault is SimpleFormalParameter &&
        patchParameterWithoutDefault is SimpleFormalParameter) {
      _matchTypes(baseParameterWithoutDefault.type,
          patchParameterWithoutDefault.type, () => '${whichParameter()} type');
    } else if (baseParameterWithoutDefault is FunctionTypedFormalParameter &&
        patchParameterWithoutDefault is FunctionTypedFormalParameter) {
      _matchTypes(
          baseParameterWithoutDefault.returnType,
          patchParameterWithoutDefault.returnType,
          () => '${whichParameter()} return type');
      _matchParameterLists(
          baseParameterWithoutDefault.parameters,
          patchParameterWithoutDefault.parameters,
          () => '${whichParameter()} parameters');
    } else if (baseParameterWithoutDefault is FieldFormalParameter &&
        patchParameter is FieldFormalParameter) {
      throw new ArgumentError(
          '${whichParameter()} cannot be patched (field formal parameters are not supported)');
    } else {
      throw new ArgumentError(
          '${whichParameter()} mismatch (different parameter kinds)');
    }
  }

  void _matchTypes(TypeName baseType, TypeName patchType, String whichType()) {
    error() => new ArgumentError("${whichType()} doesn't match");
    if (baseType == null && patchType == null) return;
    if (baseType == null || patchType == null) throw error();
    // Match up the types token by token; this is more restrictive than strictly
    // necessary, but it's easy and sufficient for patching purposes.
    Token baseToken = baseType.beginToken;
    Token patchToken = patchType.beginToken;
    while (true) {
      if (baseToken.lexeme != patchToken.lexeme) throw error();
      if (identical(baseToken, baseType.endToken) &&
          identical(patchToken, patchType.endToken)) {
        break;
      }
      if (identical(baseToken, baseType.endToken) ||
          identical(patchToken, patchType.endToken)) {
        throw error();
      }
      baseToken = baseToken.next;
      patchToken = patchToken.next;
    }
  }

  void _patchClassMembers(
      ClassDeclaration baseClass, ClassDeclaration patchClass) {
    String className = baseClass.name.name;
    List<ClassMember> membersToAppend = [];
    for (ClassMember patchMember in patchClass.members) {
      if (patchMember is FieldDeclaration) {
        if (_hasPatchAnnotation(patchMember.metadata)) {
          _failInPatch('attempts to patch a field', patchMember.offset);
        }
        List<VariableDeclaration> fields = patchMember.fields.variables;
        if (fields.length != 1) {
          _failInPatch('contains a field declaration with more than one field',
              patchMember.offset);
        }
        String name = fields[0].name.name;
        if (!_allowNewPublicNames &&
            !Identifier.isPrivateName(className) &&
            !Identifier.isPrivateName(name)) {
          _failInPatch('contains a public field', patchMember.offset);
        }
        membersToAppend.add(patchMember);
      } else if (patchMember is MethodDeclaration) {
        String name = patchMember.name.name;
        if (_hasPatchAnnotation(patchMember.metadata)) {
          for (ClassMember baseMember in baseClass.members) {
            if (baseMember is MethodDeclaration &&
                baseMember.name.name == name) {
              // Remove the "external" keyword.
              Token externalKeyword = baseMember.externalKeyword;
              if (externalKeyword != null) {
                baseMember.externalKeyword = null;
                _removeToken(externalKeyword);
              } else {
                _failExternalKeyword(name, baseMember.offset);
              }
              _matchParameterLists(
                  baseMember.parameters,
                  patchMember.parameters,
                  () => 'While patching $className.$name');
              _matchTypes(baseMember.returnType, patchMember.returnType,
                  () => 'While patching $className.$name, return type');
              // Replace the body.
              FunctionBody oldBody = baseMember.body;
              FunctionBody newBody = patchMember.body;
              _replaceNodeTokens(oldBody, newBody);
              baseMember.body = newBody;
            }
          }
        } else {
          _failIfPublicName(patchMember, name);
          membersToAppend.add(patchMember);
        }
      } else if (patchMember is ConstructorDeclaration) {
        String name = patchMember.name?.name;
        if (_hasPatchAnnotation(patchMember.metadata)) {
          for (ClassMember baseMember in baseClass.members) {
            if (baseMember is ConstructorDeclaration &&
                baseMember.name?.name == name) {
              // Remove the "external" keyword.
              Token externalKeyword = baseMember.externalKeyword;
              if (externalKeyword != null) {
                baseMember.externalKeyword = null;
                _removeToken(externalKeyword);
              } else {
                _failExternalKeyword(name, baseMember.offset);
              }
              // Factory vs. generative.
              if (baseMember.factoryKeyword == null &&
                  patchMember.factoryKeyword != null) {
                _failInPatch(
                    'attempts to replace generative constructor with a factory one',
                    patchMember.offset);
              } else if (baseMember.factoryKeyword != null &&
                  patchMember.factoryKeyword == null) {
                _failInPatch(
                    'attempts to replace factory constructor with a generative one',
                    patchMember.offset);
              }
              // The base constructor should not have initializers.
              if (baseMember.initializers.isNotEmpty) {
                throw new ArgumentError(
                    'Cannot patch external constructors with initializers '
                    'in $_baseDesc.');
              }
              _matchParameterLists(
                  baseMember.parameters, patchMember.parameters, () {
                String nameSuffix = name == null ? '' : '.$name';
                return 'While patching $className$nameSuffix';
              });
              // Prepare nodes.
              FunctionBody baseBody = baseMember.body;
              FunctionBody patchBody = patchMember.body;
              NodeList<ConstructorInitializer> baseInitializers =
                  baseMember.initializers;
              NodeList<ConstructorInitializer> patchInitializers =
                  patchMember.initializers;
              // Replace initializers and link tokens.
              if (patchInitializers.isNotEmpty) {
                baseMember.parameters.endToken
                    .setNext(patchInitializers.beginToken.previous);
                baseInitializers.addAll(patchInitializers);
                patchBody.endToken.setNext(baseBody.endToken.next);
              } else {
                _replaceNodeTokens(baseBody, patchBody);
              }
              // Replace the body.
              baseMember.body = patchBody;
            }
          }
        } else {
          if (name == null) {
            if (!_allowNewPublicNames && !Identifier.isPrivateName(className)) {
              _failInPatch(
                  'contains an unnamed public constructor', patchMember.offset);
            }
          } else {
            _failIfPublicName(patchMember, name);
          }
          membersToAppend.add(patchMember);
        }
      } else {
        String className = patchClass.name.name;
        _failInPatch('contains an unsupported class member in $className',
            patchMember.offset);
      }
    }
    // Append new class members.
    _appendToNodeList(
        baseClass.members, membersToAppend, baseClass.leftBracket);
  }

  void _patchDirectives(Source baseSource, CompilationUnit baseUnit,
      Source patchSource, CompilationUnit patchUnit) {
    for (Directive patchDirective in patchUnit.directives) {
      if (patchDirective is ImportDirective) {
        baseUnit.directives.add(patchDirective);
      } else {
        _failInPatch('contains an unsupported "$patchDirective" directive',
            patchDirective.offset);
      }
    }
  }

  void _patchTopLevelDeclarations(CompilationUnit baseUnit,
      CompilationUnit patchUnit, bool appendNewTopLevelDeclarations) {
    List<CompilationUnitMember> declarationsToAppend = [];
    for (CompilationUnitMember patchDeclaration in patchUnit.declarations) {
      if (patchDeclaration is FunctionDeclaration) {
        String name = patchDeclaration.name.name;
        if (_hasPatchAnnotation(patchDeclaration.metadata)) {
          for (CompilationUnitMember baseDeclaration in baseUnit.declarations) {
            if (patchDeclaration is FunctionDeclaration &&
                baseDeclaration is FunctionDeclaration &&
                baseDeclaration.name.name == name) {
              // Remove the "external" keyword.
              Token externalKeyword = baseDeclaration.externalKeyword;
              if (externalKeyword != null) {
                baseDeclaration.externalKeyword = null;
                _removeToken(externalKeyword);
              } else {
                _failExternalKeyword(name, baseDeclaration.offset);
              }
              _matchParameterLists(
                  baseDeclaration.functionExpression.parameters,
                  patchDeclaration.functionExpression.parameters,
                  () => 'While patching $name');
              _matchTypes(
                  baseDeclaration.returnType,
                  patchDeclaration.returnType,
                  () => 'While patching $name, return type');
              // Replace the body.
              FunctionExpression oldExpr = baseDeclaration.functionExpression;
              FunctionBody newBody = patchDeclaration.functionExpression.body;
              _replaceNodeTokens(oldExpr.body, newBody);
              oldExpr.body = newBody;
            }
          }
        } else if (appendNewTopLevelDeclarations) {
          _failIfPublicName(patchDeclaration, name);
          declarationsToAppend.add(patchDeclaration);
        }
      } else if (patchDeclaration is FunctionTypeAlias) {
        if (patchDeclaration.metadata.isNotEmpty) {
          _failInPatch('contains a function type alias with an annotation',
              patchDeclaration.offset);
        }
        _failIfPublicName(patchDeclaration, patchDeclaration.name.name);
        declarationsToAppend.add(patchDeclaration);
      } else if (patchDeclaration is ClassDeclaration) {
        if (_hasPatchAnnotation(patchDeclaration.metadata)) {
          String name = patchDeclaration.name.name;
          for (CompilationUnitMember baseDeclaration in baseUnit.declarations) {
            if (baseDeclaration is ClassDeclaration &&
                baseDeclaration.name.name == name) {
              _patchClassMembers(baseDeclaration, patchDeclaration);
            }
          }
        } else {
          _failIfPublicName(patchDeclaration, patchDeclaration.name.name);
          declarationsToAppend.add(patchDeclaration);
        }
      } else if (patchDeclaration is TopLevelVariableDeclaration &&
          !_hasPatchAnnotation(patchDeclaration.metadata)) {
        for (VariableDeclaration variable
            in patchDeclaration.variables.variables) {
          _failIfPublicName(patchDeclaration, variable.name.name);
        }
        declarationsToAppend.add(patchDeclaration);
      } else {
        _failInPatch('contains an unsupported top-level declaration',
            patchDeclaration.offset);
      }
    }
    // Append new top-level declarations.
    if (appendNewTopLevelDeclarations) {
      _appendToNodeList(baseUnit.declarations, declarationsToAppend,
          baseUnit.endToken.previous);
    }
  }

  NormalFormalParameter _withoutDefault(FormalParameter parameter) {
    if (parameter is NormalFormalParameter) {
      return parameter;
    } else if (parameter is DefaultFormalParameter) {
      return parameter.parameter;
    } else {
      // Should not happen.
      assert(false);
      return null;
    }
  }

  /**
   * Parse the given [source] into AST.
   */
  @visibleForTesting
  static CompilationUnit parse(
      Source source, AnalysisErrorListener errorListener) {
    String code = source.contents.data;

    CharSequenceReader reader = new CharSequenceReader(code);
    Scanner scanner = new Scanner(source, reader, errorListener);
    Token token = scanner.tokenize();
    LineInfo lineInfo = new LineInfo(scanner.lineStarts);

    Parser parser = new Parser(source, errorListener);
    CompilationUnit unit = parser.parseCompilationUnit(token);
    unit.lineInfo = lineInfo;
    return unit;
  }

  /**
   * Append [newNodes] to the given [nodes] and attach new tokens to the end
   * token of the last [nodes] items, or, if it is empty, to [defaultPrevToken].
   */
  static void _appendToNodeList(
      NodeList<AstNode> nodes, List<AstNode> newNodes, Token defaultPrevToken) {
    Token prevToken = nodes.endToken ?? defaultPrevToken;
    for (AstNode newNode in newNodes) {
      newNode.endToken.setNext(prevToken.next);
      prevToken.setNext(newNode.beginToken);
      nodes.add(newNode);
      prevToken = newNode.endToken;
    }
  }

  /**
   * Return `true` if [metadata] has the `@patch` annotation.
   */
  static bool _hasPatchAnnotation(List<Annotation> metadata) {
    return metadata.any((annotation) {
      Identifier name = annotation.name;
      return annotation.constructorName == null &&
          name is SimpleIdentifier &&
          name.name == 'patch';
    });
  }

  /**
   * Remove the [token] from the stream.
   */
  static void _removeToken(Token token) {
    token.previous.setNext(token.next);
  }

  /**
   * Replace tokens of the [oldNode] with tokens of the [newNode].
   */
  static void _replaceNodeTokens(AstNode oldNode, AstNode newNode) {
    oldNode.beginToken.previous.setNext(newNode.beginToken);
    newNode.endToken.setNext(oldNode.endToken.next);
  }
}
