// Copyright (c) 2025, 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 'internal.dart';
import 'ns_array.dart';
import 'ns_date.dart';
import 'ns_dictionary.dart';
import 'ns_number.dart';
import 'ns_set.dart';
import 'ns_string.dart';
import 'objective_c_bindings_generated.dart';

ObjCObject _defaultObjCConverter(Object o) =>
    throw UnimplementedError('No conversion for $o');

/// Converts a Dart object to the corresponding Objective C object.
///
/// This supports basic types like `num` and `String`. It also works on
/// collections, and recursively converts their elements.
///
/// If [dartObject] is not one of the recognized types, [convertOther] is
/// called. If [convertOther] is not provided, an error is thrown.
ObjCObject toObjCObject(
  Object? dartObject, {
  ObjCObject Function(Object) convertOther = _defaultObjCConverter,
}) => switch (dartObject) {
  null => NSNull.null$(),
  ObjCObject() => dartObject,
  num() => dartObject.toNSNumber(),
  String() => dartObject.toNSString(),
  DateTime() => dartObject.toNSDate(),
  List<Object>() => dartObject.toNSArray(convertOther: convertOther),
  Set<Object>() => dartObject.toNSSet(convertOther: convertOther),
  Map<Object, Object>() => dartObject.toNSDictionary(
    convertOther: convertOther,
  ),
  _ => convertOther(dartObject),
};

extension DartListToNSArray on List<Object> {
  NSArray toNSArray({
    ObjCObject Function(Object) convertOther = _defaultObjCConverter,
  }) => NSArray.of(map((o) => toObjCObject(o, convertOther: convertOther)));
}

extension DartSetToNSSet on Set<Object> {
  NSSet toNSSet({
    ObjCObject Function(Object) convertOther = _defaultObjCConverter,
  }) => NSSet.of(map((o) => toObjCObject(o, convertOther: convertOther)));
}

extension DartMapToNSDictionary on Map<Object, Object> {
  NSDictionary toNSDictionary({
    ObjCObject Function(Object) convertOther = _defaultObjCConverter,
  }) => NSDictionary.fromEntries(
    entries.map(
      (kv) => MapEntry(
        toObjCObject(kv.key, convertOther: convertOther) as NSCopying,
        toObjCObject(kv.value, convertOther: convertOther),
      ),
    ),
  );
}

Object _defaultDartConverter(ObjCObject o) => o;

/// Converts a Objective C object to the corresponding Dart object.
///
/// This supports basic types like `NSNumber` and `NSString`. It also works on
/// collections, and recursively converts their elements.
///
/// If [objCObject] is not one of the recognized types, [convertOther] is
/// called. If [convertOther] is not provided, [objCObject] is returned
/// directly.
Object toDartObject(
  ObjCObject objCObject, {
  Object Function(ObjCObject) convertOther = _defaultDartConverter,
}) {
  // A type-based switch, like in toObjCObject, won't work here because the
  // object could have a Dart runtime type of eg NSObject, even if the
  // underlying ObjC object that the Dart object is wrapping is a NSNumber.
  if (NSNumber.isA(objCObject)) {
    return NSNumber.as(objCObject).numValue;
  }
  if (NSString.isA(objCObject)) {
    return NSString.as(objCObject).toDartString();
  }
  if (NSDate.isA(objCObject)) {
    return NSDate.as(objCObject).toDateTime();
  }
  if (NSArray.isA(objCObject)) {
    return NSArray.as(objCObject).toDartList(convertOther: convertOther);
  }
  if (NSSet.isA(objCObject)) {
    return NSSet.as(objCObject).toDartSet(convertOther: convertOther);
  }
  if (NSDictionary.isA(objCObject)) {
    return NSDictionary.as(objCObject).toDartMap(convertOther: convertOther);
  }
  return convertOther(objCObject);
}

/// Converts a Objective C object to the corresponding Dart object.
///
/// See [toDartObject]. This method will additionally return `null` if passed an
/// `NSNull`.
Object? toNullableDartObject(
  ObjCObject objCObject, {
  Object Function(ObjCObject) convertOther = _defaultDartConverter,
}) {
  if (NSNull.isA(objCObject)) {
    return null;
  }
  return toDartObject(objCObject, convertOther: convertOther);
}

extension NSArrayToDartList on NSArray {
  /// Deep converts this [NSArray] to a Dart [List].
  ///
  /// This creates a new [List], converts all the [NSArray] elements, and adds
  /// them to the [List]. If you only need iteration and element access,
  /// [asDart] is much more efficient.
  List<Object> toDartList({
    Object Function(ObjCObject) convertOther = _defaultDartConverter,
  }) =>
      asDart().map((o) => toDartObject(o, convertOther: convertOther)).toList();
}

extension NSSetToDartSet on NSSet {
  /// Deep converts this [NSSet] to a Dart [Set].
  ///
  /// This creates a new [Set], converts all the [NSSet] elements, and adds
  /// them to the [Set]. If you only need iteration and element access,
  /// [asDart] is much more efficient.
  Set<Object> toDartSet({
    Object Function(ObjCObject) convertOther = _defaultDartConverter,
  }) =>
      asDart().map((o) => toDartObject(o, convertOther: convertOther)).toSet();
}

extension NSDictionaryToDartMap on NSDictionary {
  /// Deep converts this [NSDictionary] to a Dart [Map].
  ///
  /// This creates a new [Map], converts all the [NSDictionary] elements, and
  /// adds them to the [Map]. If you only need iteration and element access,
  /// [asDart] is much more efficient.
  Map<Object, Object> toDartMap({
    Object Function(ObjCObject) convertOther = _defaultDartConverter,
  }) => Map.fromEntries(
    asDart().entries.map(
      (kv) => MapEntry(
        toDartObject(kv.key, convertOther: convertOther),
        toDartObject(kv.value, convertOther: convertOther),
      ),
    ),
  );
}
