// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of dart.ui;

/// A composable [SceneNode].
class SceneNode extends NativeFieldWrapperClass1 {
  @pragma('vm:entry-point')
  SceneNode._create() {
    _constructor();
  }

  String? _debugName;

  /// Creates a scene node from the asset with key [assetKey].
  ///
  /// The asset must be a file produced as the output of the `scenec` importer.
  /// The constructed object should then be reused via the [shader]
  /// method to create [Shader] objects that can be used by [Shader.paint].
  static SceneNodeValue fromAsset(String assetKey) {
    // The flutter tool converts all asset keys with spaces into URI
    // encoded paths (replacing ' ' with '%20', for example). We perform
    // the same encoding here so that users can load assets with the same
    // key they have written in the pubspec.
    final String encodedKey = Uri(path: Uri.encodeFull(assetKey)).path;
    {
      final SceneNodeValue? futureSceneNode = _ipsceneRegistry[encodedKey]?.target;
      if (futureSceneNode != null) {
        return futureSceneNode;
      }
    }

    final SceneNode sceneNode = SceneNode._create();

    final Future<SceneNode> futureSceneNode = _futurize((_Callback<void> callback) {
      final String error = sceneNode._initFromAsset(assetKey, callback);
      if (error.isNotEmpty) {
        return error;
      }
      assert(() {
        sceneNode._debugName = assetKey;
        return true;
      }());

      return null;
    }).then((_) => sceneNode);

    final SceneNodeValue result = SceneNodeValue.fromFuture(futureSceneNode);
    _ipsceneRegistry[encodedKey] = WeakReference<SceneNodeValue>(result);
    return result;
  }

  static SceneNodeValue fromTransform(Float64List matrix4) {
    final SceneNode sceneNode = SceneNode._create();
    sceneNode._initFromTransform(matrix4);
    return SceneNodeValue.fromValue(sceneNode);
  }

  void addChild(SceneNode sceneNode) {
    _addChild(sceneNode);
  }

  void setTransform(Float64List matrix4) {
    _setTransform(matrix4);
  }

  void setAnimationState(String animationName, bool playing, bool loop, double weight, double timeScale) {
    _setAnimationState(animationName, playing, loop, weight, timeScale);
  }

  void seekAnimation(String animationName, double time) {
    _seekAnimation(animationName, time);
  }

  // This is a cache of ipscene-backed scene nodes that have been loaded via
  // SceneNode.fromAsset. It holds weak references to the SceneNodes so that the
  // case where an in-use ipscene is requested again can be fast, but scenes
  // that are no longer referenced are not retained because of the cache.
  static final Map<String, WeakReference<SceneNodeValue>> _ipsceneRegistry =
      <String, WeakReference<SceneNodeValue>>{};

  static Future<void> _reinitializeScene(String assetKey) async {
    final WeakReference<SceneNodeValue>? sceneRef = _ipsceneRegistry[assetKey];

    // If a scene for the asset isn't already registered, then there's no
    // need to reinitialize it.
    if (sceneRef == null) {
      return;
    }

    final Future<SceneNode>? sceneNodeFuture = sceneRef.target?.future;
    if (sceneNodeFuture == null) {
      return;
    }
    final SceneNode sceneNode = await sceneNodeFuture;

    await _futurize((_Callback<void> callback) {
      final String error = sceneNode._initFromAsset(assetKey, callback);
      if (error.isNotEmpty) {
        return error;
      }
      return null;
    });
  }

  @Native<Void Function(Handle)>(symbol: 'SceneNode::Create')
  external void _constructor();

  @Native<Handle Function(Pointer<Void>, Handle, Handle)>(symbol: 'SceneNode::initFromAsset')
  external String _initFromAsset(String assetKey, _Callback<void> completionCallback);

  @Native<Void Function(Pointer<Void>, Handle)>(symbol: 'SceneNode::initFromTransform')
  external void _initFromTransform(Float64List matrix4);

  @Native<Void Function(Pointer<Void>, Handle)>(symbol: 'SceneNode::AddChild')
  external void _addChild(SceneNode sceneNode);

  @Native<Void Function(Pointer<Void>, Handle)>(symbol: 'SceneNode::SetTransform')
  external void _setTransform(Float64List matrix4);

  @Native<Void Function(Pointer<Void>, Handle, Bool, Bool, Double, Double)>(symbol: 'SceneNode::SetAnimationState')
  external void _setAnimationState(String animationName, bool playing, bool loop, double weight, double timeScale);

  @Native<Void Function(Pointer<Void>, Handle, Double)>(symbol: 'SceneNode::SeekAnimation')
  external void _seekAnimation(String animationName, double time);

  /// Returns a fresh instance of [SceneShader].
  SceneShader sceneShader() => SceneShader._(this, debugName: _debugName);
}

class SceneNodeValue {
  SceneNodeValue._(this._future, this._value) {
    _future?.then((SceneNode result) => _value = result);
  }

  static SceneNodeValue fromFuture(Future<SceneNode> future) {
    return SceneNodeValue._(future, null);
  }

  static SceneNodeValue fromValue(SceneNode value) {
    return SceneNodeValue._(null, value);
  }

  final Future<SceneNode>? _future;
  SceneNode? _value;

  bool get isComplete {
    return _value != null;
  }

  Future<SceneNode>? get future {
    return _future;
  }

  SceneNode? get value {
    return _value;
  }

  /// Calls `callback` when the `SceneNode` has finished initializing. If the
  /// initialization is already finished, `callback` is called synchronously.
  SceneNodeValue whenComplete(void Function(SceneNode) callback) {
    if (_value == null && _future == null) {
      return this;
    }

    if (_value != null) {
      callback(_value!);
      return this;
    }

    // _future != null
    _future!.then((SceneNode node) => callback(node));
    return this;
  }
}

/// A [Shader] generated from a [SceneNode].
///
/// Instances of this class can be obtained from the
/// [SceneNode.sceneShader] method.
class SceneShader extends Shader {
  SceneShader._(SceneNode node, { String? debugName }) : _debugName = debugName, super._() {
    _constructor(node);
  }

  // ignore: unused_field
  final String? _debugName;

  void setCameraTransform(Float64List matrix4) {
    _setCameraTransform(matrix4);
  }

  /// Releases the native resources held by the [SceneShader].
  ///
  /// After this method is called, calling methods on the shader, or attaching
  /// it to a [Paint] object will fail with an exception. Calling [dispose]
  /// twice will also result in an exception being thrown.
  @override
  void dispose() {
    super.dispose();
    _dispose();
  }

  @Native<Void Function(Handle, Handle)>(symbol: 'SceneShader::Create')
  external void _constructor(SceneNode node);

  @Native<Void Function(Pointer<Void>, Handle)>(symbol: 'SceneShader::SetCameraTransform')
  external void _setCameraTransform(Float64List matrix4);

  @Native<Void Function(Pointer<Void>)>(symbol: 'SceneShader::Dispose')
  external void _dispose();
}
