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

import 'package:ffigen/src/code_generator.dart';
import 'package:ffigen/src/header_parser/sub_parsers/macro_parser.dart';
import 'package:ffigen/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart';
import 'package:ffigen/src/header_parser/sub_parsers/var_parser.dart';
import 'package:logging/logging.dart';

import 'clang_bindings/clang_bindings.dart' as clang_types;
import 'data.dart';
import 'includer.dart';
import 'sub_parsers/functiondecl_parser.dart';
import 'type_extractor/extractor.dart';
import 'utils.dart';

final _logger = Logger('ffigen.header_parser.translation_unit_parser');

late Set<Binding> _bindings;

Pointer<
        NativeFunction<
            Int32 Function(
                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
    _rootCursorVisitorPtr;

Pointer<
        NativeFunction<
            Int32 Function(
                clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>?
    _cursorDefinitionVisitorPtr;

/// Parses the translation unit and returns the generated bindings.
Set<Binding> parseTranslationUnit(clang_types.CXCursor translationUnitCursor) {
  _bindings = {};
  final resultCode = clang.clang_visitChildren(
    translationUnitCursor,
    _rootCursorVisitorPtr ??=
        Pointer.fromFunction(_rootCursorVisitor, exceptional_visitor_return),
    nullptr,
  );

  visitChildrenResultChecker(resultCode);

  return _bindings;
}

/// Child visitor invoked on translationUnitCursor [CXCursorKind.CXCursor_TranslationUnit].
int _rootCursorVisitor(clang_types.CXCursor cursor, clang_types.CXCursor parent,
    Pointer<Void> clientData) {
  try {
    if (shouldIncludeRootCursor(cursor.sourceFileName())) {
      _logger.finest('rootCursorVisitor: ${cursor.completeStringRepr()}');
      switch (clang.clang_getCursorKind(cursor)) {
        case clang_types.CXCursorKind.CXCursor_FunctionDecl:
          addAllToBindings(parseFunctionDeclaration(cursor) as List<Binding>);
          break;
        case clang_types.CXCursorKind.CXCursor_StructDecl:
        case clang_types.CXCursorKind.CXCursor_UnionDecl:
        case clang_types.CXCursorKind.CXCursor_EnumDecl:
        case clang_types.CXCursorKind.CXCursor_ObjCInterfaceDecl:
          addToBindings(_getCodeGenTypeFromCursor(cursor));
          break;
        case clang_types.CXCursorKind.CXCursor_ObjCCategoryDecl:
          addToBindings(parseObjCCategoryDeclaration(cursor));
          break;
        case clang_types.CXCursorKind.CXCursor_MacroDefinition:
          saveMacroDefinition(cursor);
          break;
        case clang_types.CXCursorKind.CXCursor_VarDecl:
          addToBindings(parseVarDeclaration(cursor));
          break;
        default:
          _logger.finer('rootCursorVisitor: CursorKind not implemented');
      }
    } else {
      _logger.finest(
          'rootCursorVisitor:(not included) ${cursor.completeStringRepr()}');
    }
  } catch (e, s) {
    _logger.severe(e);
    _logger.severe(s);
    rethrow;
  }
  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
}

/// Adds to binding if unseen and not null.
void addToBindings(Binding? b) {
  if (b != null) {
    // This is a set, and hence will not have duplicates.
    _bindings.add(b);
  }
}

/// Adds all binding if not empty.
void addAllToBindings(List<Binding> b) {
  if (b.isNotEmpty) {
    // This is a set, and hence will not have duplicates.
    _bindings.addAll(b);
  }
}

BindingType? _getCodeGenTypeFromCursor(clang_types.CXCursor cursor) {
  final t = getCodeGenType(cursor.type(), ignoreFilter: false);
  return t is BindingType ? t : null;
}

/// Visits all cursors and builds a map of usr and [CXCursor].
void buildUsrCursorDefinitionMap(clang_types.CXCursor translationUnitCursor) {
  _bindings = {};
  final resultCode = clang.clang_visitChildren(
    translationUnitCursor,
    _cursorDefinitionVisitorPtr ??= Pointer.fromFunction(
        _definitionCursorVisitor, exceptional_visitor_return),
    nullptr,
  );

  visitChildrenResultChecker(resultCode);
}

/// Child visitor invoked on translationUnitCursor [CXCursorKind.CXCursor_TranslationUnit].
int _definitionCursorVisitor(clang_types.CXCursor cursor,
    clang_types.CXCursor parent, Pointer<Void> clientData) {
  try {
    cursorIndex.saveDefinition(cursor);
  } catch (e, s) {
    _logger.severe(e);
    _logger.severe(s);
    rethrow;
  }
  return clang_types.CXChildVisitResult.CXChildVisit_Continue;
}
