/// Created by Haoyi on 2022/7/5
///

part of '../visual_feast_engine.dart';

abstract class VisualFeastRender extends RenderElement {
  @override
  String get layerName => "Default";

  @override
  int get layerPriority => 1;

  @override
  int get orderInLayer => 1;

  VisualFeastEngine? _engine;

  VisualFeastEngine get engine => _engine!;

  VisualFeastRender();

  BaseVisualFeastAnimation? _runningAttachedAnimation;
  final DoubleLinkedQueue<BaseVisualFeastAnimation> attachedAnimations = DoubleLinkedQueue();

  bool shouldUpdateOpacity = true;
  double opacity = 1.0;

  void updateOpacity() {
    if (shouldUpdateOpacity) {
      onOpacityChanged(opacity);
      shouldUpdateOpacity = false;
    }
  }

  void setOpacity(double opacity, {bool update = false}) {
    // Log.d("setOpacity: $opacity ${StackTrace.current}");
    this.opacity = opacity;
    shouldUpdateOpacity = true;
    if (update) {
      updateOpacity();
    }
  }

  void addSprite(String key, VisualFeastSprite sprite) {
    engine.addSprite(key, sprite);
  }

  VisualFeastSprite getSprite(String key) {
    return engine.getSprite(key);
  }

  void attachAnimation(BaseVisualFeastAnimation animation, {bool start = true, bool end = false}) {
    if (!animation.isCompleted) {
      if (end) {
        engine.completer.join(animation.id);
        animation.setExtras(VisualFeastExtras([engine.completer]));
      }
      attachedAnimations.add(animation..start());
    }
  }

  void resetAllAnimations() {
    _runningAttachedAnimation?.directComplete();
    attachedAnimations.clear();
  }

  void removeAnimation() {
    final extras = _runningAttachedAnimation?.extras;
    if (extras is VisualFeastExtras) {
      extras.complete(_runningAttachedAnimation!.id);
      _runningAttachedAnimation?.extras = null;
    }
    for (var animation in attachedAnimations) {
      final extras = animation.extras;
      if (extras is VisualFeastExtras) {
        extras.complete(animation.id);
        animation.extras = null;
      }
    }
    attachedAnimations.clear();
  }

  void updateAnimation(double delta) {
    final animation = _runningAttachedAnimation;
    if (animation != null && !animation.isCompleted) {
      animation.update(delta);
    } else {
      final extras = animation?.extras;
      if (extras is VisualFeastExtras) {
        extras.complete(animation!.id);
        animation.extras = null;
      }
      if (attachedAnimations.isNotEmpty) {
        final animation = attachedAnimations.removeFirst();
        if (!animation.isCompleted) {
          animation.update(delta);
          _runningAttachedAnimation = animation;
        }
      } else {
        _runningAttachedAnimation = null;
      }
    }
  }

  @override
  void dispatchFrameUpdate(double dt) {
    updateAnimation(dt);
    updateOpacity();
    onFrameUpdate(dt);
  }

  void onOpacityChanged(double opacity) {}

  @override
  void onFrameUpdate(double dt) {}

  @override
  void onRender(Canvas canvas) {}

  @mustCallSuper
  @override
  void onDetach() {
    resetAllAnimations();
    super.onDetach();
  }
}
