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

/// Extracts code_gen Type from type.
import 'dart:ffi';

import 'package:ffigen/src/code_generator.dart';
import 'package:ffigen/src/strings.dart' as strings;
import 'package:logging/logging.dart';

import '../clang_bindings/clang_bindings.dart' as clang_types;
import '../data.dart';
import '../sub_parsers/structdecl_parser.dart';
import '../translation_unit_parser.dart';
import '../type_extractor/cxtypekindmap.dart';
import '../utils.dart';

final _logger = Logger('ffigen.header_parser.extractor');
const _padding = '  ';

/// Converts cxtype to a typestring code_generator can accept.
Type getCodeGenType(Pointer<clang_types.CXType> cxtype, {String? parentName}) {
  _logger.fine('${_padding}getCodeGenType ${cxtype.completeStringRepr()}');
  final kind = cxtype.kind();

  switch (kind) {
    case clang_types.CXTypeKind.CXType_Pointer:
      final pt = clang.clang_getPointeeType_wrap(cxtype);
      final s = getCodeGenType(pt, parentName: parentName);
      pt.dispose();

      // Replace Pointer<_Dart_Handle> with Handle.
      if (config.useDartHandle &&
          s.broadType == BroadType.Struct &&
          s.struc!.usr == strings.dartHandleUsr) {
        return Type.handle();
      }
      return Type.pointer(s);
    case clang_types.CXTypeKind.CXType_Typedef:
      final spelling = cxtype.spelling();
      if (config.typedefNativeTypeMappings.containsKey(spelling)) {
        _logger.fine('  Type Mapped from typedef-map');
        return Type.nativeType(config.typedefNativeTypeMappings[spelling!]);
      }
      // Get name from supported typedef name if config allows.
      if (config.useSupportedTypedefs) {
        if (suportedTypedefToSuportedNativeType.containsKey(spelling)) {
          _logger.fine('  Type Mapped from supported typedef');
          return Type.nativeType(
              suportedTypedefToSuportedNativeType[spelling!]);
        }
      }

      // This is important or we get stuck in infinite recursion.
      final ct = clang.clang_getTypedefDeclUnderlyingType_wrap(
          clang.clang_getTypeDeclaration_wrap(cxtype));

      final s = getCodeGenType(ct, parentName: parentName ?? cxtype.spelling());
      ct.dispose();
      return s;
    case clang_types.CXTypeKind.CXType_Elaborated:
      final et = clang.clang_Type_getNamedType_wrap(cxtype);
      final s = getCodeGenType(et, parentName: parentName);
      et.dispose();
      return s;
    case clang_types.CXTypeKind.CXType_Record:
      return _extractfromRecord(cxtype, parentName);
    case clang_types.CXTypeKind.CXType_Enum:
      return Type.nativeType(
        enumNativeType,
      );
    case clang_types.CXTypeKind.CXType_FunctionProto:
      // Primarily used for function pointers.
      return _extractFromFunctionProto(cxtype, parentName);
    case clang_types.CXTypeKind.CXType_FunctionNoProto:
      // Primarily used for function types with zero arguments.
      return _extractFromFunctionProto(cxtype, parentName);
    case clang_types.CXTypeKind
        .CXType_ConstantArray: // Primarily used for constant array in struct members.
      return Type.constantArray(
        clang.clang_getNumElements_wrap(cxtype),
        clang.clang_getArrayElementType_wrap(cxtype).toCodeGenTypeAndDispose(),
      );
    case clang_types.CXTypeKind
        .CXType_IncompleteArray: // Primarily used for incomplete array in function parameters.
      return Type.incompleteArray(
        clang.clang_getArrayElementType_wrap(cxtype).toCodeGenTypeAndDispose(),
      );
    case clang_types.CXTypeKind.CXType_Bool:
      return Type.boolean();
    default:
      if (cxTypeKindToSupportedNativeTypes.containsKey(kind)) {
        return Type.nativeType(
          cxTypeKindToSupportedNativeTypes[kind!],
        );
      } else {
        _logger.fine(
            'typedeclarationCursorVisitor: getCodeGenType: Type Not Implemented, ${cxtype.completeStringRepr()}');
        return Type.unimplemented(
            'Type: ${cxtype.kindSpelling()} not implemented');
      }
  }
}

Type _extractfromRecord(
    Pointer<clang_types.CXType> cxtype, String? parentName) {
  Type type;

  final cursor = clang.clang_getTypeDeclaration_wrap(cxtype);
  _logger.fine('${_padding}_extractfromRecord: ${cursor.completeStringRepr()}');

  switch (clang.clang_getCursorKind_wrap(cursor)) {
    case clang_types.CXCursorKind.CXCursor_StructDecl:
      final cxtype = cursor.type();
      final structUsr = cursor.usr();

      // Name of typedef (parentName) is used if available.
      final structName = parentName ?? cursor.spelling();

      // Also add a struct binding, if its unseen.
      // TODO(23): Check if we should auto add struct.
      if (bindingsIndex.isSeenStruct(structUsr)) {
        type = Type.struct(bindingsIndex.getSeenStruct(structUsr));
      } else {
        final struc = parseStructDeclaration(cursor,
            name: structName, ignoreFilter: true);
        type = Type.struct(struc);

        // Add to bindings if it's not Dart_Handle.
        if (!(config.useDartHandle && structUsr == strings.dartHandleUsr)) {
          addToBindings(struc);
        }
      }

      cxtype.dispose();
      break;
    default:
      _logger.fine(
          'typedeclarationCursorVisitor: _extractfromRecord: Not Implemented, ${cursor.completeStringRepr()}');
      return Type.unimplemented(
          'Type: ${cxtype.kindSpelling()} not implemented');
  }
  cursor.dispose();
  return type;
}

// Used for function pointer arguments.
Type _extractFromFunctionProto(
    Pointer<clang_types.CXType> cxtype, String? parentName) {
  var name = parentName;

  // An empty name means the function prototype was declared in-place, instead
  // of using a typedef.
  name = name ?? '';
  final _parameters = <Parameter>[];
  final totalArgs = clang.clang_getNumArgTypes_wrap(cxtype);
  for (var i = 0; i < totalArgs; i++) {
    final t = clang.clang_getArgType_wrap(cxtype, i);
    final pt = t.toCodeGenTypeAndDispose();

    if (pt.broadType == BroadType.Struct) {
      return Type.unimplemented('Struct by value in function parameter.');
    } else if (pt.getBaseType().broadType == BroadType.Unimplemented) {
      return Type.unimplemented('Function parameter has an unsupported type.');
    }

    _parameters.add(
      Parameter(name: '', type: pt),
    );
  }

  Typedef? typedefC;
  if (bindingsIndex.isSeenFunctionTypedef(name)) {
    typedefC = bindingsIndex.getSeenFunctionTypedef(name);
  } else {
    typedefC = Typedef(
      name: name.isNotEmpty ? name : incrementalNamer.name('_typedefC'),
      typedefType: TypedefType.C,
      parameters: _parameters,
      returnType:
          clang.clang_getResultType_wrap(cxtype).toCodeGenTypeAndDispose(),
    );
    // Add to seen, if name isn't empty.
    if (name.isNotEmpty) {
      bindingsIndex.addFunctionTypedefToSeen(name, typedefC);
    }
  }

  return Type.nativeFunc(typedefC);
}
