// Copyright (c) 2019, 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 vm.bytecode.ast_remover;

import 'package:kernel/ast.dart' hide MapEntry;
import '../metadata/bytecode.dart';

/// Drops kernel AST for members with bytecode.
/// Can preserve removed AST and restore it if needed.
class ASTRemover extends Transformer {
  final BytecodeMetadataRepository metadata;
  final stashes = <Node, _Stash>{};

  ASTRemover(Component component)
      : metadata = component.metadata[new BytecodeMetadataRepository().tag] {
    stashes[component] = new _ComponentStash(component.mainMethod,
        new Map<String, MetadataRepository<dynamic>>.from(component.metadata));
    component.mainMethod = null;
    component.metadata.removeWhere((tag, md) => tag != metadata.tag);
  }

  @override
  visitLibrary(Library node) {
    stashes[node] = new _LibraryStash(
        new List<Expression>.from(node.annotations),
        new List<Field>.from(node.fields),
        new List<Procedure>.from(node.procedures),
        new List<Reference>.from(node.additionalExports));

    node.annotations.clear();
    node.fields.clear();
    node.procedures.clear();
    node.additionalExports.clear();

    super.visitLibrary(node);

    return node;
  }

  @override
  visitLibraryDependency(LibraryDependency node) {
    stashes[node] = new _LibraryDependencyStash(
        new List<Expression>.from(node.annotations));

    node.annotations.clear();

    super.visitLibraryDependency(node);

    return node;
  }

  // Still referenced from function types which may appear in class supertypes.
  @override
  visitTypedef(Typedef node) {
    stashes[node] = new _TypedefStash(node.annotations);

    node.annotations = const <Expression>[];

    super.visitTypedef(node);

    // TODO(alexmarkov): fix Typedef visitor to visit these fields.
    transformList(node.positionalParameters, this, node);
    transformList(node.namedParameters, this, node);

    return node;
  }

  // May appear in typedefs.
  @override
  visitVariableDeclaration(VariableDeclaration node) {
    stashes[node] = new _VariableDeclarationStash(node.annotations);

    node.annotations = const <Expression>[];

    super.visitVariableDeclaration(node);

    return node;
  }

  @override
  visitClass(Class node) {
    stashes[node] = new _ClassStash(
        node.annotations,
        new List<Field>.from(node.fields),
        new List<Procedure>.from(node.procedures),
        new List<Constructor>.from(node.constructors));

    node.annotations = const <Expression>[];
    node.fields.clear();
    node.procedures.clear();
    node.constructors.clear();

    super.visitClass(node);

    return node;
  }

  void restoreAST() {
    stashes.forEach((Node node, _Stash stash) {
      if (node is Component) {
        _ComponentStash componentStash = stash as _ComponentStash;
        node.mainMethod = componentStash.mainMethod;
        node.metadata.addAll(componentStash.metadata);
      } else if (node is Library) {
        _LibraryStash libraryStash = stash as _LibraryStash;
        node.annotations.addAll(libraryStash.annotations);
        node.fields.addAll(libraryStash.fields);
        node.procedures.addAll(libraryStash.procedures);
        node.additionalExports.addAll(libraryStash.additionalExports);
      } else if (node is LibraryDependency) {
        _LibraryDependencyStash libraryDependencyStash =
            stash as _LibraryDependencyStash;
        node.annotations.addAll(libraryDependencyStash.annotations);
      } else if (node is Typedef) {
        _TypedefStash typedefStash = stash as _TypedefStash;
        node.annotations = typedefStash.annotations;
      } else if (node is VariableDeclaration) {
        _VariableDeclarationStash variableDeclarationStash =
            stash as _VariableDeclarationStash;
        node.annotations = variableDeclarationStash.annotations;
      } else if (node is Class) {
        _ClassStash classStash = stash as _ClassStash;
        node.annotations = classStash.annotations;
        node.fields.addAll(classStash.fields);
        node.procedures.addAll(classStash.procedures);
        node.constructors.addAll(classStash.constructors);
      } else {
        throw 'Unexpected ${node.runtimeType} $node';
      }
    });
  }
}

abstract class _Stash {}

class _ClassStash extends _Stash {
  final List<Expression> annotations;
  final List<Field> fields;
  final List<Procedure> procedures;
  final List<Constructor> constructors;

  _ClassStash(
      this.annotations, this.fields, this.procedures, this.constructors);
}

class _LibraryStash extends _Stash {
  final List<Expression> annotations;
  final List<Field> fields;
  final List<Procedure> procedures;
  final List<Reference> additionalExports;

  _LibraryStash(
      this.annotations, this.fields, this.procedures, this.additionalExports);
}

class _LibraryDependencyStash extends _Stash {
  final List<Expression> annotations;

  _LibraryDependencyStash(this.annotations);
}

class _TypedefStash extends _Stash {
  final List<Expression> annotations;

  _TypedefStash(this.annotations);
}

class _VariableDeclarationStash extends _Stash {
  final List<Expression> annotations;

  _VariableDeclarationStash(this.annotations);
}

class _ComponentStash extends _Stash {
  final Procedure mainMethod;
  final Map<String, MetadataRepository<dynamic>> metadata;

  _ComponentStash(this.mainMethod, this.metadata);
}
