// 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.
//
// Explicit pool used for managing resources.

import "dart:async";
import 'dart:convert';
import 'dart:ffi';
import 'dart:typed_data';

import 'package:ffi/ffi.dart' as packageFfi;
import 'package:ffi/ffi.dart' show Utf8;

/// Manages native resources.
///
/// Primary implementations are [Pool] and [Unmanaged].
abstract class ResourceManager {
  /// Allocates memory on the native heap.
  ///
  /// The native memory is under management by this [ResourceManager].
  ///
  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
  /// against the default public heap. Allocation of either element size or count
  /// of 0 is undefined.
  ///
  /// Throws an ArgumentError on failure to allocate.
  Pointer<T> allocate<T extends NativeType>({int count: 1});
}

/// Manages native resources.
class Pool implements ResourceManager {
  /// Native memory under management by this [Pool].
  final List<Pointer<NativeType>> _managedMemoryPointers = [];

  /// Callbacks for releasing native resources under management by this [Pool].
  final List<Function()> _managedResourceReleaseCallbacks = [];

  /// Allocates memory on the native heap.
  ///
  /// The native memory is under management by this [Pool].
  ///
  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
  /// against the default public heap. Allocation of either element size or count
  /// of 0 is undefined.
  ///
  /// Throws an ArgumentError on failure to allocate.
  Pointer<T> allocate<T extends NativeType>({int count: 1}) {
    final p = Unmanaged().allocate<T>(count: count);
    _managedMemoryPointers.add(p);
    return p;
  }

  /// Registers [resource] in this pool.
  ///
  /// Executes [releaseCallback] on [releaseAll].
  T using<T>(T resource, Function(T) releaseCallback) {
    _managedResourceReleaseCallbacks.add(() => releaseCallback(resource));
    return resource;
  }

  /// Registers [releaseResourceCallback] to be executed on [releaseAll].
  void onReleaseAll(Function() releaseResourceCallback) {
    _managedResourceReleaseCallbacks.add(releaseResourceCallback);
  }

  /// Releases all resources that this [Pool] manages.
  void releaseAll() {
    for (final c in _managedResourceReleaseCallbacks) {
      c();
    }
    _managedResourceReleaseCallbacks.clear();
    for (final p in _managedMemoryPointers) {
      Unmanaged().free(p);
    }
    _managedMemoryPointers.clear();
  }
}

/// Creates a [Pool] to manage native resources.
///
/// If the isolate is shut down, through `Isolate.kill()`, resources are _not_ cleaned up.
R using<R>(R Function(Pool) f) {
  final p = Pool();
  try {
    return f(p);
  } finally {
    p.releaseAll();
  }
}

/// Creates a zoned [Pool] to manage native resources.
///
/// Pool is availabe through [currentPool].
///
/// Please note that all throws are caught and packaged in [RethrownError].
///
/// If the isolate is shut down, through `Isolate.kill()`, resources are _not_ cleaned up.
R usePool<R>(R Function() f) {
  final p = Pool();
  try {
    return runZoned(() => f(),
        zoneValues: {#_pool: p},
        onError: (error, st) => throw RethrownError(error, st));
  } finally {
    p.releaseAll();
  }
}

/// The [Pool] in the current zone.
Pool get currentPool => Zone.current[#_pool];

class RethrownError {
  dynamic original;
  StackTrace originalStackTrace;
  RethrownError(this.original, this.originalStackTrace);
  toString() => """RethrownError(${original})
${originalStackTrace}""";
}

/// Does not manage it's resources.
class Unmanaged implements ResourceManager {
  /// Allocates memory on the native heap.
  ///
  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
  /// against the default public heap. Allocation of either element size or count
  /// of 0 is undefined.
  ///
  /// Throws an ArgumentError on failure to allocate.
  Pointer<T> allocate<T extends NativeType>({int count = 1}) =>
      packageFfi.allocate(count: count);

  /// Releases memory on the native heap.
  ///
  /// For POSIX-based systems, this uses free. On Windows, it uses HeapFree
  /// against the default public heap. It may only be used against pointers
  /// allocated in a manner equivalent to [allocate].
  ///
  /// Throws an ArgumentError on failure to free.
  ///
  void free(Pointer pointer) => packageFfi.free(pointer);
}

/// Does not manage it's resources.
final Unmanaged unmanaged = Unmanaged();

extension Utf8InPool on String {
  /// Convert a [String] to a Utf8-encoded null-terminated C string.
  ///
  /// If 'string' contains NULL bytes, the converted string will be truncated
  /// prematurely. Unpaired surrogate code points in [string] will be preserved
  /// in the UTF-8 encoded result. See [Utf8Encoder] for details on encoding.
  ///
  /// Returns a malloc-allocated pointer to the result.
  ///
  /// The memory is managed by the [Pool] passed in as [pool].
  Pointer<Utf8> toUtf8(ResourceManager pool) {
    final units = utf8.encode(this);
    final Pointer<Uint8> result = pool.allocate<Uint8>(count: units.length + 1);
    final Uint8List nativeString = result.asTypedList(units.length + 1);
    nativeString.setAll(0, units);
    nativeString[units.length] = 0;
    return result.cast();
  }
}

extension Utf8Helpers on Pointer<Utf8> {
  /// Returns the length of a null-terminated string -- the number of (one-byte)
  /// characters before the first null byte.
  int strlen() {
    final Pointer<Uint8> array = this.cast<Uint8>();
    final Uint8List nativeString = array.asTypedList(_maxSize);
    return nativeString.indexWhere((char) => char == 0);
  }

  /// Creates a [String] containing the characters UTF-8 encoded in [this].
  ///
  /// [this] must be a zero-terminated byte sequence of valid UTF-8
  /// encodings of Unicode code points. It may also contain UTF-8 encodings of
  /// unpaired surrogate code points, which is not otherwise valid UTF-8, but
  /// which may be created when encoding a Dart string containing an unpaired
  /// surrogate. See [Utf8Decoder] for details on decoding.
  ///
  /// Returns a Dart string containing the decoded code points.
  String contents() {
    final int length = strlen();
    return utf8.decode(Uint8List.view(
        this.cast<Uint8>().asTypedList(length).buffer, 0, length));
  }
}

const int _kMaxSmi64 = (1 << 62) - 1;
const int _kMaxSmi32 = (1 << 30) - 1;
final int _maxSize = sizeOf<IntPtr>() == 8 ? _kMaxSmi64 : _kMaxSmi32;
