// Copyright (c) 2022, 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 '../code_generator.dart';
import '../context.dart';
import '../visitor/ast.dart';

/// Represents a pointer.
class PointerType extends Type {
  final Type child;

  PointerType._(this.child);

  factory PointerType(Type child) {
    if (child == objCObjectType) {
      return ObjCObjectPointer();
    } else if (child == objCBlockType) {
      return ObjCBlockPointer();
    }
    return PointerType._(child);
  }

  @override
  Type get baseType => child.baseType;

  @override
  String getCType(Context context) =>
      '${context.libs.prefix(ffiImport)}.Pointer<${child.getCType(context)}>';

  @override
  String getNativeType({String varName = ''}) =>
      '${child.getNativeType()}* $varName';

  // Both the C type and the FFI Dart type are 'Pointer<$cType>'.
  @override
  bool get sameFfiDartAndCType => true;

  @override
  String toString() => '$child*';

  @override
  String cacheKey() => '${child.cacheKey()}*';

  @override
  void visitChildren(Visitor visitor) {
    super.visitChildren(visitor);
    visitor.visit(child);
    visitor.visit(ffiImport);
  }

  @override
  void visit(Visitation visitation) => visitation.visitPointerType(this);

  @override
  bool isSupertypeOf(Type other) {
    other = other.typealiasType;
    if (other is PointerType) {
      return child.isSupertypeOf(other.child);
    }
    return false;
  }
}

/// Represents a constant array, which has a fixed size.
class ConstantArray extends PointerType {
  final int length;
  final bool useArrayType;

  ConstantArray(this.length, Type child, {required this.useArrayType})
    : super._(child);

  @override
  Type get baseArrayType => child.baseArrayType;

  @override
  bool get isIncompleteCompound => baseArrayType.isIncompleteCompound;

  @override
  String getNativeType({String varName = ''}) =>
      '${child.getNativeType()} $varName[$length]';

  @override
  String toString() => '$child[$length]';

  @override
  String cacheKey() => '${child.cacheKey()}[$length]';

  @override
  String getCType(Context context) {
    if (useArrayType) {
      final lib = context.libs.prefix(ffiImport);
      return '$lib.Array<${child.getCType(context)}>';
    }

    return super.getCType(context);
  }
}

/// Represents an incomplete array, which has an unknown size.
class IncompleteArray extends PointerType {
  IncompleteArray(super.child) : super._();

  @override
  Type get baseArrayType => child.baseArrayType;

  @override
  String getNativeType({String varName = ''}) =>
      '${child.getNativeType()}* $varName';

  @override
  String toString() => '$child[]';

  @override
  String cacheKey() => '${child.cacheKey()}[]';
}

/// A pointer to an Objective C object.
class ObjCObjectPointer extends PointerType {
  factory ObjCObjectPointer() => _inst;

  static final _inst = ObjCObjectPointer._();
  ObjCObjectPointer.__(super.child) : super._();
  ObjCObjectPointer._() : super._(objCObjectType);

  @override
  String getDartType(Context context) =>
      '${context.libs.prefix(objcPkgImport)}.ObjCObjectBase';

  @override
  String getNativeType({String varName = ''}) => 'id $varName';

  @override
  bool get sameDartAndCType => false;

  @override
  bool get sameDartAndFfiDartType => false;

  @override
  String convertDartTypeToFfiDartType(
    Context context,
    String value, {
    required bool objCRetain,
    required bool objCAutorelease,
  }) => ObjCInterface.generateGetId(value, objCRetain, objCAutorelease);

  @override
  String convertFfiDartTypeToDartType(
    Context context,
    String value, {
    required bool objCRetain,
    String? objCEnclosingClass,
  }) => '${getDartType(context)}($value, retain: $objCRetain, release: true)';

  @override
  String? generateRetain(String value) =>
      '(__bridge id)(__bridge_retained void*)($value)';

  @override
  bool isSupertypeOf(Type other) {
    other = other.typealiasType;
    // id/Object* is a supertype of all ObjC objects and blocks.
    return other is ObjCObjectPointer ||
        other is ObjCInterface ||
        other is ObjCBlock;
  }

  @override
  void visitChildren(Visitor visitor) {
    super.visitChildren(visitor);
    visitor.visit(objcPkgImport);
  }
}

/// A pointer to an Objective C block.
class ObjCBlockPointer extends ObjCObjectPointer {
  factory ObjCBlockPointer() => _inst;

  static final _inst = ObjCBlockPointer._();
  ObjCBlockPointer._() : super.__(objCBlockType);

  @override
  String getDartType(Context context) =>
      '${context.libs.prefix(objcPkgImport)}.ObjCBlockBase';

  @override
  String? generateRetain(String value) => 'objc_retainBlock($value)';

  @override
  bool isSupertypeOf(Type other) {
    other = other.typealiasType;
    return other is ObjCBlockPointer || other is ObjCBlock;
  }
}

/// A pointer to an Objective C object with protocols.
class ObjCObjectPointerWithProtocols extends ObjCObjectPointer {
  List<ObjCProtocol> protocols;

  ObjCObjectPointerWithProtocols(this.protocols)
    : assert(protocols.isNotEmpty),
      super._();

  @override
  String getDartType(Context context) => protocols.first.getDartType(context);

  @override
  bool isSupertypeOf(Type other) {
    other = other.typealiasType;
    if (other is ObjCObjectPointerWithProtocols) {
      // The "correct" logic would be to return true if each of our protocols
      // was a supertype of one of the other's protocols. But this method is
      // designed to reflect the subtyping rules of the *Dart bindings*, not the
      // ObjC types. So since the codegen just uses the first protocol, we do
      // the same here.
      return protocols.first.isSupertypeOf(other.protocols.first);
    }
    return false;
  }

  @override
  String toString() => 'id<${protocols.join(', ')}>';

  @override
  String cacheKey() => 'id<${protocols.map((p) => p.cacheKey()).join(', ')}>';

  @override
  String convertFfiDartTypeToDartType(
    Context context,
    String value, {
    required bool objCRetain,
    String? objCEnclosingClass,
  }) => protocols.first.convertFfiDartTypeToDartType(
    context,
    value,
    objCRetain: objCRetain,
    objCEnclosingClass: objCEnclosingClass,
  );

  @override
  void visitChildren(Visitor visitor) {
    super.visitChildren(visitor);
    visitor.visitAll(protocols);
  }
}
