// 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 'dart:typed_data';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/summary/api_signature.dart';
import 'package:collection/collection.dart';

/// Return the bytes of the unlinked API signature of the given [unit].
///
/// If API signatures of two units are different, they may have different APIs.
Uint8List computeUnlinkedApiSignature(CompilationUnit unit) {
  var computer = _UnitApiSignatureComputer();
  computer.compute(unit);
  return computer.signature.toByteList();
}

class _UnitApiSignatureComputer {
  static const int _kindConstructorDeclaration = 1;
  static const int _kindFieldDeclaration = 2;
  static const int _kindMethodDeclaration = 3;
  static const int _nullNode = 0;
  static const int _notNullNode = 1;
  static const int _nullToken = 0;
  static const int _notNullToken = 1;

  final ApiSignature signature = ApiSignature();

  void compute(CompilationUnit unit) {
    signature.addFeatureSet(unit.featureSet);

    signature.addInt(unit.directives.length);
    unit.directives.forEach(_addNode);

    signature.addInt(unit.declarations.length);
    for (var declaration in unit.declarations) {
      if (declaration is ClassDeclaration) {
        _addClass(declaration);
      } else if (declaration is EnumDeclaration) {
        _addEnum(declaration);
      } else if (declaration is ExtensionDeclaration) {
        _addExtension(declaration);
      } else if (declaration is FunctionDeclaration) {
        var functionExpression = declaration.functionExpression;
        _addTokens(
          declaration.beginToken,
          functionExpression.parameters?.endToken ?? declaration.name2,
        );
        _addFunctionBodyModifiers(functionExpression.body);
      } else if (declaration is MixinDeclaration) {
        _addMixin(declaration);
      } else if (declaration is TopLevelVariableDeclaration) {
        _topLevelVariableDeclaration(declaration);
      } else {
        _addNode(declaration);
      }
    }
  }

  void _addClass(ClassDeclaration node) {
    _addTokens(node.beginToken, node.leftBracket);

    bool hasConstConstructor = node.members
        .any((m) => m is ConstructorDeclaration && m.constKeyword != null);

    _addClassMembers(node.members, hasConstConstructor);
  }

  void _addClassMembers(List<ClassMember> members, bool hasConstConstructor) {
    signature.addInt(members.length);
    for (var member in members) {
      if (member is ConstructorDeclaration) {
        _addConstructorDeclaration(member);
      } else if (member is FieldDeclaration) {
        _addFieldDeclaration(member, hasConstConstructor);
      } else if (member is MethodDeclaration) {
        _addMethodDeclaration(member);
      } else {
        throw UnimplementedError('(${member.runtimeType}) $member');
      }
    }
  }

  void _addConstructorDeclaration(ConstructorDeclaration node) {
    signature.addInt(_kindConstructorDeclaration);
    _addTokens(node.beginToken, node.parameters.endToken);
    _addNodeList(node.initializers);
    _addNode(node.redirectedConstructor);
  }

  void _addEnum(EnumDeclaration node) {
    var members = node.members;

    // If not enhanced, include the whole node.
    var firstMember = members.firstOrNull;
    if (firstMember == null) {
      _addNode(node);
      return;
    }

    _addTokens(node.beginToken, firstMember.beginToken);
    _addClassMembers(members, true);
  }

  void _addExtension(ExtensionDeclaration node) {
    _addTokens(node.beginToken, node.leftBracket);
    _addClassMembers(node.members, false);
  }

  void _addFieldDeclaration(FieldDeclaration node, bool hasConstConstructor) {
    signature.addInt(_kindFieldDeclaration);

    _addToken(node.abstractKeyword);
    _addToken(node.covariantKeyword);
    _addToken(node.externalKeyword);
    _addToken(node.staticKeyword);
    _addNodeList(node.metadata);

    var variableList = node.fields;
    var includeInitializers = variableList.type == null ||
        variableList.isConst ||
        hasConstConstructor && !node.isStatic && variableList.isFinal;
    _variableList(variableList, includeInitializers);
  }

  void _addFunctionBodyModifiers(FunctionBody? node) {
    if (node != null) {
      signature.addBool(node.isSynchronous);
      signature.addBool(node.isGenerator);
      signature.addBool(node is NativeFunctionBody);
    }
  }

  void _addMethodDeclaration(MethodDeclaration node) {
    signature.addInt(_kindMethodDeclaration);
    _addTokens(
      node.beginToken,
      node.parameters?.endToken ?? node.name2,
    );
    signature.addBool(node.body is EmptyFunctionBody);
    _addFunctionBodyModifiers(node.body);
    signature.addBool(node.invokesSuperSelf);
  }

  void _addMixin(MixinDeclaration node) {
    _addTokens(node.beginToken, node.leftBracket);
    _addClassMembers(node.members, false);
  }

  void _addNode(AstNode? node) {
    if (node != null) {
      signature.addInt(_notNullNode);
      _addTokens(node.beginToken, node.endToken);
    } else {
      signature.addInt(_nullNode);
    }
  }

  void _addNodeList(List<AstNode> nodes) {
    for (var node in nodes) {
      _addNode(node);
    }
  }

  void _addToken(Token? token) {
    if (token != null) {
      signature.addInt(_notNullToken);
      signature.addString(token.lexeme);
    } else {
      signature.addInt(_nullToken);
    }
  }

  /// Appends tokens from [begin] (including), to [end] (also including).
  void _addTokens(Token begin, Token end) {
    if (begin is CommentToken) {
      begin = begin.parent!;
    }

    Token? token = begin;
    while (token != null) {
      _addToken(token);

      if (token == end) {
        break;
      }

      var nextToken = token.next;

      // Stop if EOF.
      if (nextToken == token) {
        break;
      }

      token = nextToken;
    }
  }

  void _topLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    _addToken(node.externalKeyword);
    _addNodeList(node.metadata);

    var variableList = node.variables;
    var includeInitializers = variableList.type == null || variableList.isConst;
    _variableList(variableList, includeInitializers);
  }

  void _variableList(VariableDeclarationList node, bool includeInitializers) {
    _addToken(node.keyword);
    _addToken(node.lateKeyword);
    _addNode(node.type);

    var variables = node.variables;
    signature.addInt(variables.length);

    for (var variable in variables) {
      _addToken(variable.name2);
      signature.addBool(variable.initializer != null);
      if (includeInitializers) {
        _addNode(variable.initializer);
      }
    }
  }
}
