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

import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';

MemberId computeMemberId(Element element) {
  var enclosingElement = element.enclosingElement;
  if (enclosingElement is CompilationUnitElement) {
    var memberName = element.name!;
    if (element is PropertyAccessorElement && element.isSetter) {
      memberName += '=';
    }
    return MemberId.internal(memberName);
  } else if (enclosingElement is ClassElement) {
    var memberName = element.name!;
    var className = enclosingElement.name;
    return MemberId.internal(memberName, className: className);
  } else if (enclosingElement is ExtensionElement) {
    var memberName = element.name!;
    var extensionName = enclosingElement.name;
    if (element is PropertyAccessorElement) {
      memberName = '${element.isGetter ? 'get' : 'set'}#$memberName';
    }
    return MemberId.internal('$extensionName|$memberName');
  }
  throw UnimplementedError(
      'TODO(paulberry): $element (${element.runtimeType})');
}

/// Abstract IR visitor for computing data corresponding to a node or element,
/// and record it with a generic [Id]
abstract class AstDataExtractor<T> extends GeneralizingAstVisitor<void>
    with DataRegistry<T> {
  final Uri uri;

  @override
  final Map<Id, ActualData<T>> actualMap;

  AstDataExtractor(this.uri, this.actualMap);

  NodeId computeDefaultNodeId(AstNode node) =>
      NodeId(_nodeOffset(node), IdKind.node);

  T? computeElementValue(Id id, Element element) => null;

  void computeForClass(Declaration node, Id? id) {
    if (id == null) return;
    T? value = computeNodeValue(id, node);
    registerValue(uri, _nodeOffset(node), id, value, node);
  }

  void computeForCollectionElement(CollectionElement node, NodeId? id) {
    if (id == null) return;
    T? value = computeNodeValue(id, node);
    registerValue(uri, _nodeOffset(node), id, value, node);
  }

  void computeForLibrary(LibraryElement library, Id? id) {
    if (id == null) return;
    T? value = computeElementValue(id, library);
    registerValue(uri, 0, id, value, library);
  }

  void computeForMember(Declaration node, Id? id) {
    if (id == null) return;
    T? value = computeNodeValue(id, node);
    registerValue(uri, _nodeOffset(node), id, value, node);
  }

  void computeForStatement(Statement node, NodeId? id) {
    if (id == null) return;
    T? value = computeNodeValue(id, node);
    registerValue(uri, _nodeOffset(node), id, value, node);
  }

  /// Implement this to compute the data corresponding to [node].
  ///
  /// If `null` is returned, [node] has no associated data.
  T? computeNodeValue(Id id, AstNode node);

  Id createClassId(Declaration node) {
    var element = node.declaredElement!;
    return ClassId(element.name!);
  }

  Id createLibraryId(LibraryElement node) {
    Uri uri = node.source.uri;
    if (uri.path.startsWith(r'/C:')) {
      // The `MemoryResourceProvider.convertPath` inserts '/C:' on Windows.
      uri = Uri(scheme: uri.scheme, path: uri.path.substring(3));
    }
    return LibraryId(uri);
  }

  Id createMemberId(Declaration node) {
    var element = node.declaredElement!;
    return computeMemberId(element);
  }

  NodeId createStatementId(Statement node) =>
      NodeId(_nodeOffset(node), IdKind.stmt);

  @override
  void fail(String message) {
    throw _Failure(message);
  }

  @override
  void report(Uri uri, int offset, String message) {
    // TODO(paulberry): find a way to print the error more nicely.
    print('$uri:$offset: $message');
  }

  void run(CompilationUnit unit) {
    unit.accept(this);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    computeForClass(node, createClassId(node));
    super.visitClassDeclaration(node);
  }

  @override
  void visitCollectionElement(CollectionElement node) {
    computeForCollectionElement(node, computeDefaultNodeId(node));
    super.visitCollectionElement(node);
  }

  @override
  void visitCompilationUnit(CompilationUnit node) {
    var library = node.declaredElement!.library;
    computeForLibrary(library, createLibraryId(library));
    super.visitCompilationUnit(node);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    computeForMember(node, createMemberId(node));
    super.visitConstructorDeclaration(node);
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    if (node.parent is CompilationUnit) {
      computeForMember(node, createMemberId(node));
    }
    super.visitFunctionDeclaration(node);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    computeForMember(node, createMemberId(node));
    super.visitMethodDeclaration(node);
  }

  @override
  void visitStatement(Statement node) {
    computeForStatement(
        node,
        node is ExpressionStatement
            ? createStatementId(node)
            : computeDefaultNodeId(node));
    super.visitStatement(node);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    if (node.parent!.parent is TopLevelVariableDeclaration) {
      computeForMember(node, createMemberId(node));
    } else if (node.parent!.parent is FieldDeclaration) {
      computeForMember(node, createMemberId(node));
    }
    super.visitVariableDeclaration(node);
  }

  int _nodeOffset(AstNode node) {
    int offset;
    if (node is ConditionalExpression) {
      offset = node.question.offset;
    } else if (node is BinaryExpression) {
      offset = node.operator.offset;
    } else {
      offset = node.offset;
    }
    assert(offset >= 0, "No fileOffset on $node (${node.runtimeType})");
    return offset;
  }
}

class _Failure implements Exception {
  final String? message;

  _Failure([this.message]);

  @override
  String toString() {
    if (message == null) return "Exception";
    return "Exception: $message";
  }
}
