// Copyright (c) 2020, 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:io" show File, Platform, stdout;
import "dart:typed_data" show Uint8List;

import 'package:_fe_analyzer_shared/src/parser/parser.dart'
    show IdentifierContext;

import 'package:_fe_analyzer_shared/src/scanner/token.dart'
    show CommentToken, Token;

import "package:front_end/src/fasta/util/direct_parser_ast.dart";

import 'package:front_end/src/fasta/util/direct_parser_ast_helper.dart';

void main(List<String> args) {
  Uri uri = Platform.script;
  uri = uri.resolve("../../kernel/lib/ast.dart");
  Uint8List bytes = new File.fromUri(uri).readAsBytesSync();
  DirectParserASTContentCompilationUnitEnd ast =
      getAST(bytes, includeBody: true, includeComments: true);
  Map<String, DirectParserASTContentTopLevelDeclarationEnd> classes = {};
  for (DirectParserASTContentTopLevelDeclarationEnd cls in ast.getClasses()) {
    DirectParserASTContentIdentifierHandle identifier = cls.getIdentifier();
    assert(classes[identifier.token] == null);
    classes[identifier.token.toString()] = cls;
  }

  Set<String?> goodNames = {"TreeNode"};
  Map<Token, Replacement> replacements = {};
  for (MapEntry<String, DirectParserASTContentTopLevelDeclarationEnd> entry
      in classes.entries) {
    DirectParserASTContentTopLevelDeclarationEnd cls = entry.value;

    // Simple "class hierarchy" to only work on TreeNodes.
    if (goodNames.contains(entry.key)) {
      // Cached good.
    } else {
      // Check if good.
      String? parent = getExtends(cls);
      DirectParserASTContentTopLevelDeclarationEnd? parentCls = classes[parent];
      List<String?> allParents = [parent];
      while (
          parent != null && parentCls != null && !goodNames.contains(parent)) {
        parent = getExtends(parentCls);
        allParents.add(parent);
        parentCls = classes[parent];
      }
      if (goodNames.contains(parent)) {
        goodNames.addAll(allParents);
      } else {
        continue;
      }
    }

    DirectParserASTContentClassDeclarationEnd classDeclaration =
        cls.getClassDeclaration();
    DirectParserASTContentClassOrMixinOrExtensionBodyEnd classOrMixinBody =
        classDeclaration.getClassOrMixinOrExtensionBody();

    Set<String> namedClassConstructors = {};
    Set<String> namedFields = {};
    for (DirectParserASTContentMemberEnd member
        in classOrMixinBody.getMembers()) {
      if (member.isClassConstructor()) {
        DirectParserASTContentClassConstructorEnd constructor =
            member.getClassConstructor();
        Token nameToken = constructor.beginToken;
        // String name = nameToken.lexeme;
        if (nameToken.next!.lexeme == ".") {
          nameToken = nameToken.next!.next!;
          // name += ".$nameToken";
          namedClassConstructors.add(nameToken.lexeme);
        }
        if (nameToken.next!.lexeme == ".") {
          throw "Unexpected";
        }
      } else if (member.isClassFields()) {
        DirectParserASTContentClassFieldsEnd classFields =
            member.getClassFields();
        Token identifierToken = classFields.getFieldIdentifiers().single!.token;
        String identifier = identifierToken.toString();
        namedFields.add(identifier);
      }
    }

    // If there isn't a `frozen` field in `TreeNode` we insert one.
    if (entry.key == "TreeNode" && !namedFields.contains("frozen")) {
      Token classBraceToken = classOrMixinBody.beginToken;
      assert(classBraceToken.lexeme == "{");
      replacements[classBraceToken] = new Replacement(
          classBraceToken, classBraceToken, "{\n  bool frozen = false;");
    }

    for (DirectParserASTContentMemberEnd member
        in classOrMixinBody.getMembers()) {
      if (member.isClassConstructor()) {
        processConstructor(
            member, replacements, namedClassConstructors, namedFields);
      } else if (member.isClassFields()) {
        processField(member, entry, replacements);
      }
    }
  }
  Token? token = ast.getBegin().token;

  int endOfLast = token.end;
  while (token != null) {
    CommentToken? comment = token.precedingComments;
    while (comment != null) {
      if (comment.offset > endOfLast) {
        for (int i = endOfLast; i < comment.offset; i++) {
          int byte = bytes[i];
          stdout.writeCharCode(byte);
        }
      }

      stdout.write(comment.value());
      endOfLast = comment.end;
      comment = comment.next as CommentToken?;
    }

    if (token.isEof) break;
    if (token.offset > endOfLast) {
      for (int i = endOfLast; i < token.offset; i++) {
        int byte = bytes[i];
        stdout.writeCharCode(byte);
      }
    }

    Replacement? replacement = replacements[token];
    if (replacement != null) {
      stdout.write(replacement.replacement);
      token = replacement.endToken;
    } else {
      stdout.write(token.lexeme);
    }
    endOfLast = token.end;
    token = token.next;
  }
}

void processField(
    DirectParserASTContentMemberEnd member,
    MapEntry<String, DirectParserASTContentTopLevelDeclarationEnd> entry,
    Map<Token, Replacement> replacements) {
  DirectParserASTContentClassFieldsEnd classFields = member.getClassFields();

  if (classFields.count != 1) {
    throw "Notice ${classFields.count}";
  }

  Token identifierToken = classFields.getFieldIdentifiers().single!.token;
  String identifier = identifierToken.toString();

  if (identifier == "frozen" && entry.key == "TreeNode") return;

  if (classFields.staticToken != null) {
    return;
  }
  bool isFinal = false;
  if (classFields.varFinalOrConst?.toString() == "final") {
    isFinal = true;
  }

  DirectParserASTContentTypeHandle? type = classFields.getFirstType();
  String typeString = "dynamic";
  if (type != null) {
    Token token = type.beginToken;
    typeString = "";
    while (token != identifierToken) {
      typeString += " ${token.lexeme}";
      token = token.next!;
    }
    typeString = typeString.trim();
  }

  DirectParserASTContentFieldInitializerEnd? initializer =
      classFields.getFieldInitializer();
  String initializerString = "";
  if (initializer != null) {
    Token token = initializer.assignment;
    Token endToken = initializer.token;
    while (token != endToken) {
      initializerString += " ${token.lexeme}";
      token = token.next!;
    }
    initializerString = initializerString.trim();
  }

  Token beginToken = classFields.beginToken;
  Token endToken = classFields.endToken;
  // ignore: unnecessary_null_comparison
  assert(beginToken != null);
  // ignore: unnecessary_null_comparison
  assert(endToken != null);

  String frozenCheckCode =
      """if (frozen) throw "Trying to modify frozen node!";""";

  if (identifier == "parent" && entry.key == "TreeNode") {
    // We update the parent for libraries for instance all the time (e.g.
    // when we link).
    frozenCheckCode = "";
  } else if (identifier == "transformerFlags" && entry.key == "Member") {
    // The verifier changes this for all libraries
    // (and then change it back again).
    frozenCheckCode = "";
  } else if (identifier == "initializer" && entry.key == "Field") {
    // The constant evaluator does some stuff here. Only allow that
    // when it's basically a no-op though!
    frozenCheckCode = """
    if (frozen) {
      if (_initializer is ConstantExpression && newValue is ConstantExpression) {
        if ((_initializer as ConstantExpression).constant == newValue.constant) {
          _initializer = newValue;
          return;
        }
      }
      throw "Trying to modify frozen node!";
    }""";
  }

  if (!isFinal) {
    replacements[beginToken] = new Replacement(beginToken, endToken, """
$typeString _$identifier$initializerString;
$typeString get $identifier => _$identifier;
void set $identifier($typeString newValue) {
    $frozenCheckCode
  _$identifier = newValue;
}""");
  } else {
    // Don't create setter for final field.
    // TODO: Possibly wrap a list for instance of a non-writable one.
    replacements[beginToken] = new Replacement(beginToken, endToken, """
final $typeString _$identifier$initializerString;
$typeString get $identifier => _$identifier;""");
  }
}

void processConstructor(
    DirectParserASTContentMemberEnd member,
    Map<Token, Replacement> replacements,
    Set<String> namedClassConstructors,
    Set<String> namedFields) {
  DirectParserASTContentClassConstructorEnd constructor =
      member.getClassConstructor();
  DirectParserASTContentFormalParametersEnd formalParameters =
      constructor.getFormalParameters();
  List<DirectParserASTContentFormalParameterEnd> parameters =
      formalParameters.getFormalParameters();

  for (DirectParserASTContentFormalParameterEnd parameter in parameters) {
    Token token = parameter.getBegin().token;
    if (token.lexeme != "this") {
      continue;
    }
    // Here `this.foo` can just be replace with `this._foo`.
    Token afterDot = token.next!.next!;
    replacements[afterDot] = new Replacement(afterDot, afterDot, "_$afterDot");
  }

  DirectParserASTContentOptionalFormalParametersEnd? optionalFormalParameters =
      formalParameters.getOptionalFormalParameters();
  Set<String> addInitializers = {};
  if (optionalFormalParameters != null) {
    List<DirectParserASTContentFormalParameterEnd> parameters =
        optionalFormalParameters.getFormalParameters();

    for (DirectParserASTContentFormalParameterEnd parameter in parameters) {
      Token token = parameter.getBegin().token;
      if (token.lexeme != "this") {
        continue;
      }
      // Here `this.foo` can't just be replace with `this._foo` as it is
      // (possibly) named and we can't use private stuff in named.
      // Instead we replace it with `dynamic foo` here and add an
      // initializer `this._foo = foo`.
      Token afterDot = token.next!.next!;
      addInitializers.add(afterDot.lexeme);
      replacements[token] = new Replacement(token, token.next!, "dynamic ");
    }
  }

  DirectParserASTContentInitializersEnd? initializers =
      constructor.getInitializers();

  // First patch up any existing initializers.
  if (initializers != null) {
    List<DirectParserASTContentInitializerEnd> actualInitializers =
        initializers.getInitializers();
    for (DirectParserASTContentInitializerEnd initializer
        in actualInitializers) {
      Token token = initializer.getBegin().token;
      // This is only afterDot if there's a dot --- which (probably) is
      // only there if there's a `this`.
      Token afterDot = token.next!.next!;

      // We need to check it's not a redirecting call!
      // TODO(jensj): Handle redirects like this:
      //  class C {
      //    C();
      //    C.redirect() : this();
      //  }
      if (token.lexeme == "this" &&
          namedClassConstructors.contains(afterDot.lexeme)) {
        // Redirect!
        continue;
      }

      if (token.lexeme == "this") {
        // Here `this.foo` can just be replace with `this._foo`.
        assert(namedFields.contains(afterDot.lexeme));
        replacements[afterDot] =
            new Replacement(afterDot, afterDot, "_$afterDot");
      } else if (token.lexeme == "super") {
        // Don't try to patch this one.
      } else if (token.lexeme == "assert") {
        List<DirectParserASTContentIdentifierHandle> identifiers = initializer
            .recursivelyFind<DirectParserASTContentIdentifierHandle>();
        for (Token token in identifiers.map((e) => e.token)) {
          if (namedFields.contains(token.lexeme)) {
            replacements[token] = new Replacement(token, token, "_$token");
          }
        }
      } else {
        assert(namedFields.contains(token.lexeme),
            "${token.lexeme} isn't a known field among ${namedFields}");
        replacements[token] = new Replacement(token, token, "_$token");
      }
    }
  }

  // Then add any new ones.
  if (addInitializers.isNotEmpty && initializers == null) {
    // No initializers => Fake one by inserting `:` and all `_foo = foo`
    // entries.
    Token endToken = formalParameters.endToken;
    String initializerString =
        addInitializers.map((e) => "this._$e = $e").join(",\n");
    replacements[endToken] =
        new Replacement(endToken, endToken, ") : $initializerString");
  } else if (addInitializers.isNotEmpty) {
    // Add to existing initializer list. We add them as the first one(s)
    // so we don't have to insert before the potential super call.
    DirectParserASTContentInitializersBegin firstOne = initializers!.getBegin();
    Token colon = firstOne.token;
    assert(colon.lexeme == ":");
    String initializerString =
        addInitializers.map((e) => "this._$e = $e").join(", ");
    replacements[colon] =
        new Replacement(colon, colon, ": $initializerString,");
  }

  // If there are anything in addInitializers we need to patch
  // up the body too -- if we replace `{this.foo}` with `{dynamic foo}`
  // and the body says `foo = 42;` before that would change the field,
  // now it will change the parameter value. We must patch up all usages
  // - even reads to work on things like
  //  class C {
  //    int field1;
  //    int field2;
  //    C(this.field1) : field2 = field1 + 1;
  //  }
  if (addInitializers.isNotEmpty) {
    DirectParserASTContentBlockFunctionBodyEnd? blockFunctionBody =
        constructor.getBlockFunctionBody();
    if (blockFunctionBody != null) {
      List<DirectParserASTContentIdentifierHandle> identifiers =
          blockFunctionBody
              .recursivelyFind<DirectParserASTContentIdentifierHandle>();
      for (DirectParserASTContentIdentifierHandle identifier in identifiers) {
        Token token = identifier.token;
        IdentifierContext context = identifier.context;
        if (namedFields.contains(token.lexeme) &&
            addInitializers.contains(token.lexeme)) {
          // For now naively assume that if it's a continuation it says
          // `this.`
          if (!context.isContinuation) {
            replacements[token] = new Replacement(token, token, "_$token");
          }
        }
      }
    }
  }
}

class Replacement {
  final Token beginToken;
  final Token endToken;
  final String replacement;

  Replacement(this.beginToken, this.endToken, this.replacement);
}

String? getExtends(DirectParserASTContentTopLevelDeclarationEnd cls) {
  DirectParserASTContentClassDeclarationEnd classDeclaration =
      cls.getClassDeclaration();

  DirectParserASTContentClassExtendsHandle classExtends =
      classDeclaration.getClassExtends();
  Token? extendsKeyword = classExtends.extendsKeyword;
  if (extendsKeyword == null) {
    return null;
  } else {
    return extendsKeyword.next.toString();
  }
}

void debugDumpNode(DirectParserASTContent node) {
  node.children!.forEach((element) {
    print("${element.what} (${element.deprecatedArguments}) "
        "(${element.children})");
  });
}

void debugDumpNodeRecursively(DirectParserASTContent node,
    {String indent = ""}) {
  print("$indent${node.what} (${node.deprecatedArguments})");
  if (node.children == null) return;
  node.children!.forEach((element) {
    print("$indent${element.what} (${element.deprecatedArguments})");
    if (element.children != null) {
      element.children!.forEach((element) {
        debugDumpNodeRecursively(element, indent: "  $indent");
      });
    }
  });
}
