package com.airbnb.lottie;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PathMeasure;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView;

import androidx.annotation.FloatRange;
import androidx.annotation.IntDef;
import androidx.annotation.IntRange;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;

import com.airbnb.lottie.animation.LPaint;
import com.airbnb.lottie.manager.FontAssetManager;
import com.airbnb.lottie.manager.ImageAssetManager;
import com.airbnb.lottie.model.Font;
import com.airbnb.lottie.model.KeyPath;
import com.airbnb.lottie.model.Marker;
import com.airbnb.lottie.model.layer.CompositionLayer;
import com.airbnb.lottie.parser.LayerParser;
import com.airbnb.lottie.utils.Logger;
import com.airbnb.lottie.utils.LottieThreadFactory;
import com.airbnb.lottie.utils.LottieValueAnimator;
import com.airbnb.lottie.utils.MiscUtils;
import com.airbnb.lottie.value.LottieFrameInfo;
import com.airbnb.lottie.value.LottieValueCallback;
import com.airbnb.lottie.value.SimpleLottieValueCallback;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * This can be used to show an lottie animation in any place that would normally take a drawable.
 *
 * @see <a href="http://airbnb.io/lottie">Full Documentation</a>
 */
@SuppressWarnings({"WeakerAccess"})
public class LottieDrawable extends Drawable implements Drawable.Callback, Animatable {
  private interface LazyCompositionTask {
    void run(LottieComposition composition);
  }

  /**
   * Internal record keeping of the desired play state when {@link #isVisible()} transitions to or is false.
   * <p>
   * If the animation was playing when it becomes invisible or play/pause is called on it while it is invisible, it will
   * store the state and then take the appropriate action when the drawable becomes visible again.
   */
  private enum OnVisibleAction {
    NONE,
    PLAY,
    RESUME,
  }

  private LottieComposition composition;
  private final LottieValueAnimator animator = new LottieValueAnimator();

  // Call animationsEnabled() instead of using these fields directly.
  private boolean systemAnimationsEnabled = true;
  private boolean ignoreSystemAnimationsDisabled = false;

  private boolean safeMode = false;
  private OnVisibleAction onVisibleAction = OnVisibleAction.NONE;

  private final ArrayList<LazyCompositionTask> lazyCompositionTasks = new ArrayList<>();

  /**
   * ImageAssetManager created automatically by Lottie for views.
   */
  @Nullable
  private ImageAssetManager imageAssetManager;
  @Nullable
  private String imageAssetsFolder;
  @Nullable
  private ImageAssetDelegate imageAssetDelegate;
  @Nullable
  private FontAssetManager fontAssetManager;
  @Nullable
  private Map<String, Typeface> fontMap;
  /**
   * Will be set if manually overridden by {@link #setDefaultFontFileExtension(String)}.
   * This must be stored as a field in case it is set before the font asset delegate
   * has been created.
   */
  @Nullable String defaultFontFileExtension;
  @Nullable
  FontAssetDelegate fontAssetDelegate;
  @Nullable
  TextDelegate textDelegate;
  private boolean enableMergePaths;
  private boolean maintainOriginalImageBounds = false;
  private boolean clipToCompositionBounds = true;
  @Nullable
  private CompositionLayer compositionLayer;
  private int alpha = 255;
  private boolean performanceTrackingEnabled;
  private boolean outlineMasksAndMattes;
  private boolean isApplyingOpacityToLayersEnabled;

  private RenderMode renderMode = RenderMode.AUTOMATIC;
  /**
   * The actual render mode derived from {@link #renderMode}.
   */
  private boolean useSoftwareRendering = false;
  private final Matrix renderingMatrix = new Matrix();
  private Bitmap softwareRenderingBitmap;
  private Canvas softwareRenderingCanvas;
  private Rect canvasClipBounds;
  private RectF canvasClipBoundsRectF;
  private Paint softwareRenderingPaint;
  private Rect softwareRenderingSrcBoundsRect;
  private Rect softwareRenderingDstBoundsRect;
  private RectF softwareRenderingDstBoundsRectF;
  private RectF softwareRenderingTransformedBounds;
  private Matrix softwareRenderingOriginalCanvasMatrix;
  private Matrix softwareRenderingOriginalCanvasMatrixInverse;

  private AsyncUpdates asyncUpdates = AsyncUpdates.AUTOMATIC;
  private final ValueAnimator.AnimatorUpdateListener progressUpdateListener = animation -> {
    if (getAsyncUpdatesEnabled()) {
      // Render a new frame.
      // If draw is called while lastDrawnProgress is still recent enough, it will
      // draw straight away and then enqueue a background setProgress immediately after draw
      // finishes.
      invalidateSelf();
    } else if (compositionLayer != null) {
      compositionLayer.setProgress(animator.getAnimatedValueAbsolute());
    }
  };

  /**
   * Ensures that setProgress and draw will never happen at the same time on different threads.
   * If that were to happen, parts of the animation may be on one frame while other parts would
   * be on another.
   */
  private final Semaphore setProgressDrawLock = new Semaphore(1);
  /**
   * The executor that {@link AsyncUpdates} will be run on.
   * <p/>
   * Defaults to a core size of 0 so that when no animations are playing, there will be no
   * idle cores consuming resources.
   * <p/>
   * Allows up to two active threads so that if there are many animations, they can all work in parallel.
   * Two was arbitrarily chosen but should be sufficient for most uses cases. In the case of a single
   * animation, this should never exceed one.
   * <p/>
   * Each thread will timeout after 35ms which gives it enough time to persist for one frame, one dropped frame
   * and a few extra ms just in case.
   */
  private static final Executor setProgressExecutor = new ThreadPoolExecutor(0, 2, 35, TimeUnit.MILLISECONDS,
      new LinkedBlockingQueue<>(), new LottieThreadFactory());
  private final Runnable updateProgressRunnable = () -> {
    CompositionLayer compositionLayer = this.compositionLayer;
    if (compositionLayer == null) {
      return;
    }
    try {
      setProgressDrawLock.acquire();
      compositionLayer.setProgress(animator.getAnimatedValueAbsolute());
    } catch (InterruptedException e) {
      // Do nothing.
    } finally {
      setProgressDrawLock.release();
    }
  };
  private float lastDrawnProgress = -Float.MAX_VALUE;
  private static final float MAX_DELTA_MS_ASYNC_SET_PROGRESS = 3 / 60f * 1000;

  /**
   * True if the drawable has not been drawn since the last invalidateSelf.
   * We can do this to prevent things like bounds from getting recalculated
   * many times.
   */
  private boolean isDirty = false;

  @IntDef({RESTART, REVERSE})
  @Retention(RetentionPolicy.SOURCE)
  public @interface RepeatMode {
  }

  /**
   * When the animation reaches the end and <code>repeatCount</code> is INFINITE
   * or a positive value, the animation restarts from the beginning.
   */
  public static final int RESTART = ValueAnimator.RESTART;
  /**
   * When the animation reaches the end and <code>repeatCount</code> is INFINITE
   * or a positive value, the animation reverses direction on every iteration.
   */
  public static final int REVERSE = ValueAnimator.REVERSE;
  /**
   * This value used used with the {@link #setRepeatCount(int)} property to repeat
   * the animation indefinitely.
   */
  public static final int INFINITE = ValueAnimator.INFINITE;

  public LottieDrawable() {
    animator.addUpdateListener(progressUpdateListener);
  }

  /**
   * Returns whether or not any layers in this composition has masks.
   */
  public boolean hasMasks() {
    return compositionLayer != null && compositionLayer.hasMasks();
  }

  /**
   * Returns whether or not any layers in this composition has a matte layer.
   */
  public boolean hasMatte() {
    return compositionLayer != null && compositionLayer.hasMatte();
  }

  public boolean enableMergePathsForKitKatAndAbove() {
    return enableMergePaths;
  }

  /**
   * Enable this to get merge path support for devices running KitKat (19) and above.
   * <p>
   * Merge paths currently don't work if the the operand shape is entirely contained within the
   * first shape. If you need to cut out one shape from another shape, use an even-odd fill type
   * instead of using merge paths.
   */
  public void enableMergePathsForKitKatAndAbove(boolean enable) {
    if (enableMergePaths == enable) {
      return;
    }

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
      Logger.warning("Merge paths are not supported pre-Kit Kat.");
      return;
    }
    enableMergePaths = enable;
    if (composition != null) {
      buildCompositionLayer();
    }
  }

  public boolean isMergePathsEnabledForKitKatAndAbove() {
    return enableMergePaths;
  }

  /**
   * Sets whether or not Lottie should clip to the original animation composition bounds.
   * <p>
   * Defaults to true.
   */
  public void setClipToCompositionBounds(boolean clipToCompositionBounds) {
    if (clipToCompositionBounds != this.clipToCompositionBounds) {
      this.clipToCompositionBounds = clipToCompositionBounds;
      CompositionLayer compositionLayer = this.compositionLayer;
      if (compositionLayer != null) {
        compositionLayer.setClipToCompositionBounds(clipToCompositionBounds);
      }
      invalidateSelf();
    }
  }

  /**
   * Gets whether or not Lottie should clip to the original animation composition bounds.
   * <p>
   * Defaults to true.
   */
  public boolean getClipToCompositionBounds() {
    return clipToCompositionBounds;
  }

  /**
   * If you use image assets, you must explicitly specify the folder in assets/ in which they are
   * located because bodymovin uses the name filenames across all compositions (img_#).
   * Do NOT rename the images themselves.
   * <p>
   * If your images are located in src/main/assets/airbnb_loader/ then call
   * `setImageAssetsFolder("airbnb_loader/");`.
   * <p>
   * <p>
   * Be wary if you are using many images, however. Lottie is designed to work with vector shapes
   * from After Effects. If your images look like they could be represented with vector shapes,
   * see if it is possible to convert them to shape layers and re-export your animation. Check
   * the documentation at http://airbnb.io/lottie for more information about importing shapes from
   * Sketch or Illustrator to avoid this.
   */
  public void setImagesAssetsFolder(@Nullable String imageAssetsFolder) {
    this.imageAssetsFolder = imageAssetsFolder;
  }

  @Nullable
  public String getImageAssetsFolder() {
    return imageAssetsFolder;
  }

  /**
   * When true, dynamically set bitmaps will be drawn with the exact bounds of the original animation, regardless of the bitmap size.
   * When false, dynamically set bitmaps will be drawn at the top left of the original image but with its own bounds.
   * <p>
   * Defaults to false.
   */
  public void setMaintainOriginalImageBounds(boolean maintainOriginalImageBounds) {
    this.maintainOriginalImageBounds = maintainOriginalImageBounds;
  }

  /**
   * When true, dynamically set bitmaps will be drawn with the exact bounds of the original animation, regardless of the bitmap size.
   * When false, dynamically set bitmaps will be drawn at the top left of the original image but with its own bounds.
   * <p>
   * Defaults to false.
   */
  public boolean getMaintainOriginalImageBounds() {
    return maintainOriginalImageBounds;
  }

  /**
   * Create a composition with {@link LottieCompositionFactory}
   *
   * @return True if the composition is different from the previously set composition, false otherwise.
   */
  public boolean setComposition(LottieComposition composition) {
    if (this.composition == composition) {
      return false;
    }

    isDirty = true;
    clearComposition();
    this.composition = composition;
    buildCompositionLayer();
    animator.setComposition(composition);
    setProgress(animator.getAnimatedFraction());

    // We copy the tasks to a new ArrayList so that if this method is called from multiple threads,
    // then there won't be two iterators iterating and removing at the same time.
    Iterator<LazyCompositionTask> it = new ArrayList<>(lazyCompositionTasks).iterator();
    while (it.hasNext()) {
      LazyCompositionTask t = it.next();
      // The task should never be null but it appears to happen in rare cases. Maybe it's an oem-specific or ART bug.
      // https://github.com/airbnb/lottie-android/issues/1702
      if (t != null) {
        t.run(composition);
      }
      it.remove();
    }
    lazyCompositionTasks.clear();

    composition.setPerformanceTrackingEnabled(performanceTrackingEnabled);
    computeRenderMode();

    // Ensure that ImageView updates the drawable width/height so it can
    // properly calculate its drawable matrix.
    Callback callback = getCallback();
    if (callback instanceof ImageView) {
      ((ImageView) callback).setImageDrawable(null);
      ((ImageView) callback).setImageDrawable(this);
    }

    return true;
  }

  /**
   * Call this to set whether or not to render with hardware or software acceleration.
   * Lottie defaults to Automatic which will use hardware acceleration unless:
   * 1) There are dash paths and the device is pre-Pie.
   * 2) There are more than 4 masks and mattes and the device is pre-Pie.
   * Hardware acceleration is generally faster for those devices unless
   * there are many large mattes and masks in which case there is a lot
   * of GPU uploadTexture thrashing which makes it much slower.
   * <p>
   * In most cases, hardware rendering will be faster, even if you have mattes and masks.
   * However, if you have multiple mattes and masks (especially large ones), you
   * should test both render modes. You should also test on pre-Pie and Pie+ devices
   * because the underlying rendering engine changed significantly.
   *
   * @see <a href="https://developer.android.com/guide/topics/graphics/hardware-accel#unsupported">Android Hardware Acceleration</a>
   */
  public void setRenderMode(RenderMode renderMode) {
    this.renderMode = renderMode;
    computeRenderMode();
  }

  /**
   * Returns the current value of {@link AsyncUpdates}. Refer to the docs for {@link AsyncUpdates} for more info.
   */
  public AsyncUpdates getAsyncUpdates() {
    return asyncUpdates;
  }

  /**
   * Similar to {@link #getAsyncUpdates()} except it returns the actual
   * boolean value for whether async updates are enabled or not.
   * This is useful when the mode is automatic and you want to know
   * whether automatic is defaulting to enabled or not.
   */
  public boolean getAsyncUpdatesEnabled() {
    return asyncUpdates == AsyncUpdates.ENABLED;
  }

  /**
   * **Note: this API is experimental and may changed.**
   * <p/>
   * Sets the current value for {@link AsyncUpdates}. Refer to the docs for {@link AsyncUpdates} for more info.
   */
  public void setAsyncUpdates(AsyncUpdates asyncUpdates) {
    this.asyncUpdates = asyncUpdates;
  }

  /**
   * Returns the actual render mode being used. It will always be {@link RenderMode#HARDWARE} or {@link RenderMode#SOFTWARE}.
   * When the render mode is set to AUTOMATIC, the value will be derived from {@link RenderMode#useSoftwareRendering(int, boolean, int)}.
   */
  public RenderMode getRenderMode() {
    return useSoftwareRendering ? RenderMode.SOFTWARE : RenderMode.HARDWARE;
  }

  private void computeRenderMode() {
    LottieComposition composition = this.composition;
    if (composition == null) {
      return;
    }
    useSoftwareRendering = renderMode.useSoftwareRendering(
        Build.VERSION.SDK_INT, composition.hasDashPattern(), composition.getMaskAndMatteCount());
  }

  public void setPerformanceTrackingEnabled(boolean enabled) {
    performanceTrackingEnabled = enabled;
    if (composition != null) {
      composition.setPerformanceTrackingEnabled(enabled);
    }
  }

  /**
   * Enable this to debug slow animations by outlining masks and mattes. The performance overhead of the masks and mattes will
   * be proportional to the surface area of all of the masks/mattes combined.
   * <p>
   * DO NOT leave this enabled in production.
   */
  public void setOutlineMasksAndMattes(boolean outline) {
    if (outlineMasksAndMattes == outline) {
      return;
    }
    outlineMasksAndMattes = outline;
    if (compositionLayer != null) {
      compositionLayer.setOutlineMasksAndMattes(outline);
    }
  }

  @Nullable
  public PerformanceTracker getPerformanceTracker() {
    if (composition != null) {
      return composition.getPerformanceTracker();
    }
    return null;
  }

  /**
   * Sets whether to apply opacity to the each layer instead of shape.
   * <p>
   * Opacity is normally applied directly to a shape. In cases where translucent shapes overlap, applying opacity to a layer will be more accurate
   * at the expense of performance.
   * <p>
   * The default value is false.
   * <p>
   * Note: This process is very expensive. The performance impact will be reduced when hardware acceleration is enabled.
   *
   * @see android.view.View#setLayerType(int, android.graphics.Paint)
   * @see LottieAnimationView#setRenderMode(RenderMode)
   */
  public void setApplyingOpacityToLayersEnabled(boolean isApplyingOpacityToLayersEnabled) {
    this.isApplyingOpacityToLayersEnabled = isApplyingOpacityToLayersEnabled;
  }

  /**
   * This API no longer has any effect.
   */
  @Deprecated
  public void disableExtraScaleModeInFitXY() {
  }

  public boolean isApplyingOpacityToLayersEnabled() {
    return isApplyingOpacityToLayersEnabled;
  }

  private void buildCompositionLayer() {
    LottieComposition composition = this.composition;
    if (composition == null) {
      return;
    }
    compositionLayer = new CompositionLayer(
        this, LayerParser.parse(composition), composition.getLayers(), composition);
    if (outlineMasksAndMattes) {
      compositionLayer.setOutlineMasksAndMattes(true);
    }
    compositionLayer.setClipToCompositionBounds(clipToCompositionBounds);
  }

  public void clearComposition() {
    if (animator.isRunning()) {
      animator.cancel();
      if (!isVisible()) {
        onVisibleAction = OnVisibleAction.NONE;
      }
    }
    composition = null;
    compositionLayer = null;
    imageAssetManager = null;
    lastDrawnProgress = -Float.MAX_VALUE;
    animator.clearComposition();
    invalidateSelf();
  }

  /**
   * If you are experiencing a device specific crash that happens during drawing, you can set this to true
   * for those devices. If set to true, draw will be wrapped with a try/catch which will cause Lottie to
   * render an empty frame rather than crash your app.
   * <p>
   * Ideally, you will never need this and the vast majority of apps and animations won't. However, you may use
   * this for very specific cases if absolutely necessary.
   */
  public void setSafeMode(boolean safeMode) {
    this.safeMode = safeMode;
  }

  @Override
  public void invalidateSelf() {
    if (isDirty) {
      return;
    }
    isDirty = true;
    final Callback callback = getCallback();
    if (callback != null) {
      callback.invalidateDrawable(this);
    }
  }

  @Override
  public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
    this.alpha = alpha;
    invalidateSelf();
  }

  @Override
  public int getAlpha() {
    return alpha;
  }

  @Override
  public void setColorFilter(@Nullable ColorFilter colorFilter) {
    Logger.warning("Use addColorFilter instead.");
  }

  @Override
  public int getOpacity() {
    return PixelFormat.TRANSLUCENT;
  }

  /**
   * Helper for the async execution path to potentially call setProgress
   * before drawing if the current progress has drifted sufficiently far
   * from the last set progress.
   *
   * @see AsyncUpdates
   * @see #setAsyncUpdates(AsyncUpdates)
   */
  private boolean shouldSetProgressBeforeDrawing() {
    LottieComposition composition = this.composition;
    if (composition == null) {
      return false;
    }
    float lastDrawnProgress = this.lastDrawnProgress;
    float currentProgress = animator.getAnimatedValueAbsolute();
    this.lastDrawnProgress = currentProgress;

    float duration = composition.getDuration();

    float deltaProgress = Math.abs(currentProgress - lastDrawnProgress);
    float deltaMs = deltaProgress * duration;
    return deltaMs >= MAX_DELTA_MS_ASYNC_SET_PROGRESS;
  }

  @Override
  public void draw(@NonNull Canvas canvas) {
    CompositionLayer compositionLayer = this.compositionLayer;
    if (compositionLayer == null) {
      return;
    }
    boolean asyncUpdatesEnabled = getAsyncUpdatesEnabled();
    Log.d("Gabe", "draw asyncUpdatesEnabled " + asyncUpdatesEnabled);
    try {
      if (asyncUpdatesEnabled) {
        setProgressDrawLock.acquire();
      }
      L.beginSection("Drawable#draw");

      if (asyncUpdatesEnabled && shouldSetProgressBeforeDrawing()) {
        setProgress(animator.getAnimatedValueAbsolute());
      }

      if (safeMode) {
        try {
          if (useSoftwareRendering) {
            renderAndDrawAsBitmap(canvas, compositionLayer);
          } else {
            drawDirectlyToCanvas(canvas);
          }
        } catch (Throwable e) {
          Logger.error("Lottie crashed in draw!", e);
        }
      } else {
        if (useSoftwareRendering) {
          renderAndDrawAsBitmap(canvas, compositionLayer);
        } else {
          drawDirectlyToCanvas(canvas);
        }
      }

      isDirty = false;
    } catch (InterruptedException e) {
      // Do nothing.
    } finally {
      L.endSection("Drawable#draw");
      if (asyncUpdatesEnabled) {
        setProgressDrawLock.release();
        if (compositionLayer.getProgress() != animator.getAnimatedValueAbsolute()) {
          setProgressExecutor.execute(updateProgressRunnable);
        }
      }
    }
  }

  /**
   * To be used by lottie-compose only.
   */
  @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
  public void draw(Canvas canvas, Matrix matrix) {
    CompositionLayer compositionLayer = this.compositionLayer;
    LottieComposition composition = this.composition;
    if (compositionLayer == null || composition == null) {
      return;
    }
    boolean asyncUpdatesEnabled = getAsyncUpdatesEnabled();
    try {
      if (asyncUpdatesEnabled) {
        setProgressDrawLock.acquire();
        if (shouldSetProgressBeforeDrawing()) {
          setProgress(animator.getAnimatedValueAbsolute());
        }
      }

      if (useSoftwareRendering) {
        canvas.save();
        canvas.concat(matrix);
        renderAndDrawAsBitmap(canvas, compositionLayer);
        canvas.restore();
      } else {
        compositionLayer.draw(canvas, matrix, alpha);
      }
      isDirty = false;
    } catch (InterruptedException e) {
      // Do nothing.
    } finally {
      if (asyncUpdatesEnabled) {
        setProgressDrawLock.release();
        if (compositionLayer.getProgress() != animator.getAnimatedValueAbsolute()) {
          setProgressExecutor.execute(updateProgressRunnable);
        }
      }
    }
  }

  // <editor-fold desc="animator">

  @MainThread
  @Override
  public void start() {
    Callback callback = getCallback();
    if (callback instanceof View && ((View) callback).isInEditMode()) {
      // Don't auto play when in edit mode.
      return;
    }
    playAnimation();
  }

  @MainThread
  @Override
  public void stop() {
    endAnimation();
  }

  @Override
  public boolean isRunning() {
    return isAnimating();
  }

  /**
   * Plays the animation from the beginning. If speed is {@literal <} 0, it will start at the end
   * and play towards the beginning
   */
  @MainThread
  public void playAnimation() {
    if (compositionLayer == null) {
      lazyCompositionTasks.add(c -> playAnimation());
      return;
    }

    computeRenderMode();
    if (animationsEnabled() || getRepeatCount() == 0) {
      if (isVisible()) {
        animator.playAnimation();
        onVisibleAction = OnVisibleAction.NONE;
      } else {
        onVisibleAction = OnVisibleAction.PLAY;
      }
    }
    if (!animationsEnabled()) {
      setFrame((int) (getSpeed() < 0 ? getMinFrame() : getMaxFrame()));
      animator.endAnimation();
      if (!isVisible()) {
        onVisibleAction = OnVisibleAction.NONE;
      }
    }
  }

  @MainThread
  public void endAnimation() {
    lazyCompositionTasks.clear();
    animator.endAnimation();
    if (!isVisible()) {
      onVisibleAction = OnVisibleAction.NONE;
    }
  }

  /**
   * Continues playing the animation from its current position. If speed {@literal <} 0, it will play backwards
   * from the current position.
   */
  @MainThread
  public void resumeAnimation() {
    if (compositionLayer == null) {
      lazyCompositionTasks.add(c -> resumeAnimation());
      return;
    }

    computeRenderMode();
    if (animationsEnabled() || getRepeatCount() == 0) {
      if (isVisible()) {
        animator.resumeAnimation();
        onVisibleAction = OnVisibleAction.NONE;
      } else {
        onVisibleAction = OnVisibleAction.RESUME;
      }
    }
    if (!animationsEnabled()) {
      setFrame((int) (getSpeed() < 0 ? getMinFrame() : getMaxFrame()));
      animator.endAnimation();
      if (!isVisible()) {
        onVisibleAction = OnVisibleAction.NONE;
      }
    }
  }

  /**
   * Sets the minimum frame that the animation will start from when playing or looping.
   */
  public void setMinFrame(final int minFrame) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMinFrame(minFrame));
      return;
    }
    animator.setMinFrame(minFrame);
  }

  /**
   * Returns the minimum frame set by {@link #setMinFrame(int)} or {@link #setMinProgress(float)}
   */
  public float getMinFrame() {
    return animator.getMinFrame();
  }

  /**
   * Sets the minimum progress that the animation will start from when playing or looping.
   */
  public void setMinProgress(final float minProgress) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMinProgress(minProgress));
      return;
    }
    setMinFrame((int) MiscUtils.lerp(composition.getStartFrame(), composition.getEndFrame(), minProgress));
  }

  /**
   * Sets the maximum frame that the animation will end at when playing or looping.
   * <p>
   * The value will be clamped to the composition bounds. For example, setting Integer.MAX_VALUE would result in the same
   * thing as composition.endFrame.
   */
  public void setMaxFrame(final int maxFrame) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMaxFrame(maxFrame));
      return;
    }
    animator.setMaxFrame(maxFrame + 0.99f);
  }

  /**
   * Returns the maximum frame set by {@link #setMaxFrame(int)} or {@link #setMaxProgress(float)}
   */
  public float getMaxFrame() {
    return animator.getMaxFrame();
  }

  /**
   * Sets the maximum progress that the animation will end at when playing or looping.
   */
  public void setMaxProgress(@FloatRange(from = 0f, to = 1f) final float maxProgress) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMaxProgress(maxProgress));
      return;
    }
    animator.setMaxFrame(MiscUtils.lerp(composition.getStartFrame(), composition.getEndFrame(), maxProgress));
  }

  /**
   * Sets the minimum frame to the start time of the specified marker.
   *
   * @throws IllegalArgumentException if the marker is not found.
   */
  public void setMinFrame(final String markerName) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMinFrame(markerName));
      return;
    }
    Marker marker = composition.getMarker(markerName);
    if (marker == null) {
      throw new IllegalArgumentException("Cannot find marker with name " + markerName + ".");
    }
    setMinFrame((int) marker.startFrame);
  }

  /**
   * Sets the maximum frame to the start time + duration of the specified marker.
   *
   * @throws IllegalArgumentException if the marker is not found.
   */
  public void setMaxFrame(final String markerName) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMaxFrame(markerName));
      return;
    }
    Marker marker = composition.getMarker(markerName);
    if (marker == null) {
      throw new IllegalArgumentException("Cannot find marker with name " + markerName + ".");
    }
    setMaxFrame((int) (marker.startFrame + marker.durationFrames));
  }

  /**
   * Sets the minimum and maximum frame to the start time and start time + duration
   * of the specified marker.
   *
   * @throws IllegalArgumentException if the marker is not found.
   */
  public void setMinAndMaxFrame(final String markerName) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMinAndMaxFrame(markerName));
      return;
    }
    Marker marker = composition.getMarker(markerName);
    if (marker == null) {
      throw new IllegalArgumentException("Cannot find marker with name " + markerName + ".");
    }
    int startFrame = (int) marker.startFrame;
    setMinAndMaxFrame(startFrame, startFrame + (int) marker.durationFrames);
  }

  /**
   * Sets the minimum and maximum frame to the start marker start and the maximum frame to the end marker start.
   * playEndMarkerStartFrame determines whether or not to play the frame that the end marker is on. If the end marker
   * represents the end of the section that you want, it should be true. If the marker represents the beginning of the
   * next section, it should be false.
   *
   * @throws IllegalArgumentException if either marker is not found.
   */
  public void setMinAndMaxFrame(final String startMarkerName, final String endMarkerName, final boolean playEndMarkerStartFrame) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMinAndMaxFrame(startMarkerName, endMarkerName, playEndMarkerStartFrame));
      return;
    }
    Marker startMarker = composition.getMarker(startMarkerName);
    if (startMarker == null) {
      throw new IllegalArgumentException("Cannot find marker with name " + startMarkerName + ".");
    }
    int startFrame = (int) startMarker.startFrame;

    final Marker endMarker = composition.getMarker(endMarkerName);
    if (endMarker == null) {
      throw new IllegalArgumentException("Cannot find marker with name " + endMarkerName + ".");
    }
    int endFrame = (int) (endMarker.startFrame + (playEndMarkerStartFrame ? 1f : 0f));

    setMinAndMaxFrame(startFrame, endFrame);
  }

  /**
   * @see #setMinFrame(int)
   * @see #setMaxFrame(int)
   */
  public void setMinAndMaxFrame(final int minFrame, final int maxFrame) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMinAndMaxFrame(minFrame, maxFrame));
      return;
    }
    // Adding 0.99 ensures that the maxFrame itself gets played.
    animator.setMinAndMaxFrames(minFrame, maxFrame + 0.99f);
  }

  /**
   * @see #setMinProgress(float)
   * @see #setMaxProgress(float)
   */
  public void setMinAndMaxProgress(
      @FloatRange(from = 0f, to = 1f) final float minProgress,
      @FloatRange(from = 0f, to = 1f) final float maxProgress) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setMinAndMaxProgress(minProgress, maxProgress));
      return;
    }

    setMinAndMaxFrame((int) MiscUtils.lerp(composition.getStartFrame(), composition.getEndFrame(), minProgress),
        (int) MiscUtils.lerp(composition.getStartFrame(), composition.getEndFrame(), maxProgress));
  }

  /**
   * Reverses the current animation speed. This does NOT play the animation.
   *
   * @see #setSpeed(float)
   * @see #playAnimation()
   * @see #resumeAnimation()
   */
  public void reverseAnimationSpeed() {
    animator.reverseAnimationSpeed();
  }

  /**
   * Sets the playback speed. If speed {@literal <} 0, the animation will play backwards.
   */
  public void setSpeed(float speed) {
    animator.setSpeed(speed);
  }

  /**
   * Returns the current playback speed. This will be {@literal <} 0 if the animation is playing backwards.
   */
  public float getSpeed() {
    return animator.getSpeed();
  }

  public void addAnimatorUpdateListener(ValueAnimator.AnimatorUpdateListener updateListener) {
    animator.addUpdateListener(updateListener);
  }

  public void removeAnimatorUpdateListener(ValueAnimator.AnimatorUpdateListener updateListener) {
    animator.removeUpdateListener(updateListener);
  }

  public void removeAllUpdateListeners() {
    animator.removeAllUpdateListeners();
    animator.addUpdateListener(progressUpdateListener);
  }

  public void addAnimatorListener(Animator.AnimatorListener listener) {
    animator.addListener(listener);
  }

  public void removeAnimatorListener(Animator.AnimatorListener listener) {
    animator.removeListener(listener);
  }

  public void removeAllAnimatorListeners() {
    animator.removeAllListeners();
  }

  @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  public void addAnimatorPauseListener(Animator.AnimatorPauseListener listener) {
    animator.addPauseListener(listener);
  }

  @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  public void removeAnimatorPauseListener(Animator.AnimatorPauseListener listener) {
    animator.removePauseListener(listener);
  }

  /**
   * Sets the progress to the specified frame.
   * If the composition isn't set yet, the progress will be set to the frame when
   * it is.
   */
  public void setFrame(final int frame) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setFrame(frame));
      return;
    }

    animator.setFrame(frame);
  }

  /**
   * Get the currently rendered frame.
   */
  public int getFrame() {
    return (int) animator.getFrame();
  }

  public void setProgress(@FloatRange(from = 0f, to = 1f) final float progress) {
    if (composition == null) {
      lazyCompositionTasks.add(c -> setProgress(progress));
      return;
    }
    L.beginSection("Drawable#setProgress");
    animator.setFrame(composition.getFrameForProgress(progress));
    L.endSection("Drawable#setProgress");
  }

  /**
   * @see #setRepeatCount(int)
   */
  @Deprecated
  public void loop(boolean loop) {
    animator.setRepeatCount(loop ? ValueAnimator.INFINITE : 0);
  }

  /**
   * Defines what this animation should do when it reaches the end. This
   * setting is applied only when the repeat count is either greater than
   * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
   *
   * @param mode {@link #RESTART} or {@link #REVERSE}
   */
  public void setRepeatMode(@RepeatMode int mode) {
    animator.setRepeatMode(mode);
  }

  /**
   * Defines what this animation should do when it reaches the end.
   *
   * @return either one of {@link #REVERSE} or {@link #RESTART}
   */
  @SuppressLint("WrongConstant")
  @RepeatMode
  public int getRepeatMode() {
    return animator.getRepeatMode();
  }

  /**
   * Sets how many times the animation should be repeated. If the repeat
   * count is 0, the animation is never repeated. If the repeat count is
   * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
   * into account. The repeat count is 0 by default.
   *
   * @param count the number of times the animation should be repeated
   */
  public void setRepeatCount(int count) {
    animator.setRepeatCount(count);
  }

  /**
   * Defines how many times the animation should repeat. The default value
   * is 0.
   *
   * @return the number of times the animation should repeat, or {@link #INFINITE}
   */
  public int getRepeatCount() {
    return animator.getRepeatCount();
  }


  @SuppressWarnings("unused")
  public boolean isLooping() {
    return animator.getRepeatCount() == ValueAnimator.INFINITE;
  }

  public boolean isAnimating() {
    // On some versions of Android, this is called from the LottieAnimationView constructor, before animator was created.
    // https://github.com/airbnb/lottie-android/issues/1430
    //noinspection ConstantConditions
    if (animator == null) {
      return false;
    }
    return animator.isRunning();
  }

  boolean isAnimatingOrWillAnimateOnVisible() {
    if (isVisible()) {
      return animator.isRunning();
    } else {
      return onVisibleAction == OnVisibleAction.PLAY || onVisibleAction == OnVisibleAction.RESUME;
    }
  }

  private boolean animationsEnabled() {
    return systemAnimationsEnabled || ignoreSystemAnimationsDisabled;
  }

  /**
   * Tell Lottie that system animations are disabled. When using {@link LottieAnimationView} or Compose {@code LottieAnimation}, this is done
   * automatically. However, if you are using LottieDrawable on its own, you should set this to false when
   * {@link com.airbnb.lottie.utils.Utils#getAnimationScale(Context)} is 0.
   */
  public void setSystemAnimationsAreEnabled(Boolean areEnabled) {
    systemAnimationsEnabled = areEnabled;
  }

// </editor-fold>

  /**
   * Allows ignoring system animations settings, therefore allowing animations to run even if they are disabled.
   * <p>
   * Defaults to false.
   *
   * @param ignore if true animations will run even when they are disabled in the system settings.
   */
  public void setIgnoreDisabledSystemAnimations(boolean ignore) {
    ignoreSystemAnimationsDisabled = ignore;
  }

  /**
   * Lottie files can specify a target frame rate. By default, Lottie ignores it and re-renders
   * on every frame. If that behavior is undesirable, you can set this to true to use the composition
   * frame rate instead.
   * <p>
   * Note: composition frame rates are usually lower than display frame rates
   * so this will likely make your animation feel janky. However, it may be desirable
   * for specific situations such as pixel art that are intended to have low frame rates.
   */
  public void setUseCompositionFrameRate(boolean useCompositionFrameRate) {
    animator.setUseCompositionFrameRate(useCompositionFrameRate);
  }

  /**
   * Use this if you can't bundle images with your app. This may be useful if you download the
   * animations from the network or have the images saved to an SD Card. In that case, Lottie
   * will defer the loading of the bitmap to this delegate.
   * <p>
   * Be wary if you are using many images, however. Lottie is designed to work with vector shapes
   * from After Effects. If your images look like they could be represented with vector shapes,
   * see if it is possible to convert them to shape layers and re-export your animation. Check
   * the documentation at <a href="http://airbnb.io/lottie">http://airbnb.io/lottie</a> for more information about importing shapes from
   * Sketch or Illustrator to avoid this.
   */
  public void setImageAssetDelegate(ImageAssetDelegate assetDelegate) {
    this.imageAssetDelegate = assetDelegate;
    if (imageAssetManager != null) {
      imageAssetManager.setDelegate(assetDelegate);
    }
  }

  /**
   * Use this to manually set fonts.
   */
  public void setFontAssetDelegate(FontAssetDelegate assetDelegate) {
    this.fontAssetDelegate = assetDelegate;
    if (fontAssetManager != null) {
      fontAssetManager.setDelegate(assetDelegate);
    }
  }

  /**
   * Set a map from font name keys to Typefaces.
   * The keys can be in the form:
   * * fontFamily
   * * fontFamily-fontStyle
   * * fontName
   * All 3 are defined as fName, fFamily, and fStyle in the Lottie file.
   * <p>
   * If you change a value in fontMap, create a new map or call
   * {@link #invalidateSelf()}. Setting the same map again will noop.
   */
  public void setFontMap(@Nullable Map<String, Typeface> fontMap) {
    if (fontMap == this.fontMap) {
      return;
    }
    this.fontMap = fontMap;
    invalidateSelf();
  }

  public void setTextDelegate(@SuppressWarnings("NullableProblems") TextDelegate textDelegate) {
    this.textDelegate = textDelegate;
  }

  @Nullable
  public TextDelegate getTextDelegate() {
    return textDelegate;
  }

  public boolean useTextGlyphs() {
    return fontMap == null && textDelegate == null && composition.getCharacters().size() > 0;
  }

  public LottieComposition getComposition() {
    return composition;
  }

  public void cancelAnimation() {
    lazyCompositionTasks.clear();
    animator.cancel();
    if (!isVisible()) {
      onVisibleAction = OnVisibleAction.NONE;
    }
  }

  public void pauseAnimation() {
    lazyCompositionTasks.clear();
    animator.pauseAnimation();
    if (!isVisible()) {
      onVisibleAction = OnVisibleAction.NONE;
    }
  }

  @FloatRange(from = 0f, to = 1f)
  public float getProgress() {
    return animator.getAnimatedValueAbsolute();
  }

  @Override
  public int getIntrinsicWidth() {
    return composition == null ? -1 : composition.getBounds().width();
  }

  @Override
  public int getIntrinsicHeight() {
    return composition == null ? -1 : composition.getBounds().height();
  }

  /**
   * Takes a {@link KeyPath}, potentially with wildcards or globstars and resolve it to a list of
   * zero or more actual {@link KeyPath Keypaths} that exist in the current animation.
   * <p>
   * If you want to set value callbacks for any of these values, it is recommend to use the
   * returned {@link KeyPath} objects because they will be internally resolved to their content
   * and won't trigger a tree walk of the animation contents when applied.
   */
  public List<KeyPath> resolveKeyPath(KeyPath keyPath) {
    if (compositionLayer == null) {
      Logger.warning("Cannot resolve KeyPath. Composition is not set yet.");
      return Collections.emptyList();
    }
    List<KeyPath> keyPaths = new ArrayList<>();
    compositionLayer.resolveKeyPath(keyPath, 0, keyPaths, new KeyPath());
    return keyPaths;
  }

  /**
   * Add an property callback for the specified {@link KeyPath}. This {@link KeyPath} can resolve
   * to multiple contents. In that case, the callback's value will apply to all of them.
   * <p>
   * Internally, this will check if the {@link KeyPath} has already been resolved with
   * {@link #resolveKeyPath(KeyPath)} and will resolve it if it hasn't.
   */
  public <T> void addValueCallback(
      final KeyPath keyPath, final T property, @Nullable final LottieValueCallback<T> callback) {
    if (compositionLayer == null) {
      lazyCompositionTasks.add(c -> addValueCallback(keyPath, property, callback));
      return;
    }
    boolean invalidate;
    if (keyPath == KeyPath.COMPOSITION) {
      compositionLayer.addValueCallback(property, callback);
      invalidate = true;
    } else if (keyPath.getResolvedElement() != null) {
      keyPath.getResolvedElement().addValueCallback(property, callback);
      invalidate = true;
    } else {
      List<KeyPath> elements = resolveKeyPath(keyPath);

      for (int i = 0; i < elements.size(); i++) {
        //noinspection ConstantConditions
        elements.get(i).getResolvedElement().addValueCallback(property, callback);
      }
      invalidate = !elements.isEmpty();
    }
    if (invalidate) {
      invalidateSelf();
      if (property == LottieProperty.TIME_REMAP) {
        // Time remapping values are read in setProgress. In order for the new value
        // to apply, we have to re-set the progress with the current progress so that the
        // time remapping can be reapplied.
        setProgress(getProgress());
      }
    }
  }

  /**
   * Overload of {@link #addValueCallback(KeyPath, Object, LottieValueCallback)} that takes an interface. This allows you to use a single abstract
   * method code block in Kotlin such as:
   * drawable.addValueCallback(yourKeyPath, LottieProperty.COLOR) { yourColor }
   */
  public <T> void addValueCallback(KeyPath keyPath, T property,
      final SimpleLottieValueCallback<T> callback) {
    addValueCallback(keyPath, property, new LottieValueCallback<T>() {
      @Override
      public T getValue(LottieFrameInfo<T> frameInfo) {
        return callback.getValue(frameInfo);
      }
    });
  }


  /**
   * Allows you to modify or clear a bitmap that was loaded for an image either automatically
   * through {@link #setImagesAssetsFolder(String)} or with an {@link ImageAssetDelegate}.
   *
   * @return the previous Bitmap or null.
   */
  @Nullable
  public Bitmap updateBitmap(String id, @Nullable Bitmap bitmap) {
    ImageAssetManager bm = getImageAssetManager();
    if (bm == null) {
      Logger.warning("Cannot update bitmap. Most likely the drawable is not added to a View " +
          "which prevents Lottie from getting a Context.");
      return null;
    }
    Bitmap ret = bm.updateBitmap(id, bitmap);
    invalidateSelf();
    return ret;
  }

  /**
   * @deprecated use {@link #getBitmapForId(String)}.
   */
  @Nullable
  @Deprecated
  public Bitmap getImageAsset(String id) {
    ImageAssetManager bm = getImageAssetManager();
    if (bm != null) {
      return bm.bitmapForId(id);
    }
    LottieImageAsset imageAsset = composition == null ? null : composition.getImages().get(id);
    if (imageAsset != null) {
      return imageAsset.getBitmap();
    }
    return null;
  }

  /**
   * Returns the bitmap that will be rendered for the given id in the Lottie animation file.
   * The id is the asset reference id stored in the "id" property of each object in the "assets" array.
   * <p>
   * The returned bitmap could be from:
   * * Embedded in the animation file as a base64 string.
   * * In the same directory as the animation file.
   * * In the same zip file as the animation file.
   * * Returned from an {@link ImageAssetDelegate}.
   * or null if the image doesn't exist from any of those places.
   */
  @Nullable
  public Bitmap getBitmapForId(String id) {
    ImageAssetManager assetManager = getImageAssetManager();
    if (assetManager != null) {
      return assetManager.bitmapForId(id);
    }
    return null;
  }

  /**
   * Returns the {@link LottieImageAsset} that will be rendered for the given id in the Lottie animation file.
   * The id is the asset reference id stored in the "id" property of each object in the "assets" array.
   * <p>
   * The returned bitmap could be from:
   * * Embedded in the animation file as a base64 string.
   * * In the same directory as the animation file.
   * * In the same zip file as the animation file.
   * * Returned from an {@link ImageAssetDelegate}.
   * or null if the image doesn't exist from any of those places.
   */
  @Nullable
  public LottieImageAsset getLottieImageAssetForId(String id) {
    LottieComposition composition = this.composition;
    if (composition == null) {
      return null;
    }
    return composition.getImages().get(id);
  }

  private ImageAssetManager getImageAssetManager() {
    if (imageAssetManager != null && !imageAssetManager.hasSameContext(getContext())) {
      imageAssetManager = null;
    }

    if (imageAssetManager == null) {
      imageAssetManager = new ImageAssetManager(getCallback(),
          imageAssetsFolder, imageAssetDelegate, composition.getImages());
    }

    return imageAssetManager;
  }

  @Nullable
  @RestrictTo(RestrictTo.Scope.LIBRARY)
  public Typeface getTypeface(Font font) {
    Map<String, Typeface> fontMap = this.fontMap;
    if (fontMap != null) {
      String key = font.getFamily();
      if (fontMap.containsKey(key)) {
        return fontMap.get(key);
      }
      key = font.getName();
      if (fontMap.containsKey(key)) {
        return fontMap.get(key);
      }
      key = font.getFamily() + "-" + font.getStyle();
      if (fontMap.containsKey(key)) {
        return fontMap.get(key);
      }
    }

    FontAssetManager assetManager = getFontAssetManager();
    if (assetManager != null) {
      return assetManager.getTypeface(font);
    }
    return null;
  }

  private FontAssetManager getFontAssetManager() {
    if (getCallback() == null) {
      // We can't get a bitmap since we can't get a Context from the callback.
      return null;
    }

    if (fontAssetManager == null) {
      fontAssetManager = new FontAssetManager(getCallback(), fontAssetDelegate);
      String defaultExtension = this.defaultFontFileExtension;
      if (defaultExtension != null) {
        fontAssetManager.setDefaultFontFileExtension(defaultFontFileExtension);
      }
    }

    return fontAssetManager;
  }

  /**
   * By default, Lottie will look in src/assets/fonts/FONT_NAME.ttf
   * where FONT_NAME is the fFamily specified in your Lottie file.
   * If your fonts have a different extension, you can override the
   * default here.
   * <p>
   * Alternatively, you can use {@link #setFontAssetDelegate(FontAssetDelegate)}
   * for more control.
   *
   * @see #setFontAssetDelegate(FontAssetDelegate)
   */
  public void setDefaultFontFileExtension(String extension) {
    defaultFontFileExtension = extension;
    FontAssetManager fam = getFontAssetManager();
    if (fam != null) {
      fam.setDefaultFontFileExtension(extension);
    }
  }

  @Nullable
  private Context getContext() {
    Callback callback = getCallback();
    if (callback == null) {
      return null;
    }

    if (callback instanceof View) {
      return ((View) callback).getContext();
    }
    return null;
  }

  @Override public boolean setVisible(boolean visible, boolean restart) {
    // Sometimes, setVisible(false) gets called twice in a row. If we don't check wasNotVisibleAlready, we could
    // wind up clearing the onVisibleAction value for the second call.
    boolean wasNotVisibleAlready = !isVisible();
    boolean ret = super.setVisible(visible, restart);

    if (visible) {
      if (onVisibleAction == OnVisibleAction.PLAY) {
        playAnimation();
      } else if (onVisibleAction == OnVisibleAction.RESUME) {
        resumeAnimation();
      }
    } else {
      if (animator.isRunning()) {
        pauseAnimation();
        onVisibleAction = OnVisibleAction.RESUME;
      } else if (!wasNotVisibleAlready) {
        onVisibleAction = OnVisibleAction.NONE;
      }
    }
    return ret;
  }

  /**
   * These Drawable.Callback methods proxy the calls so that this is the drawable that is
   * actually invalidated, not a child one which will not pass the view's validateDrawable check.
   */
  @Override
  public void invalidateDrawable(@NonNull Drawable who) {
    Callback callback = getCallback();
    if (callback == null) {
      return;
    }
    callback.invalidateDrawable(this);
  }

  @Override
  public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
    Callback callback = getCallback();
    if (callback == null) {
      return;
    }
    callback.scheduleDrawable(this, what, when);
  }

  @Override
  public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
    Callback callback = getCallback();
    if (callback == null) {
      return;
    }
    callback.unscheduleDrawable(this, what);
  }

  /**
   * Hardware accelerated render path.
   */
  private void drawDirectlyToCanvas(Canvas canvas) {
    CompositionLayer compositionLayer = this.compositionLayer;
    LottieComposition composition = this.composition;
    if (compositionLayer == null || composition == null) {
      return;
    }

    renderingMatrix.reset();
    Rect bounds = getBounds();
    if (!bounds.isEmpty()) {
      // In fitXY mode, the scale doesn't take effect.
      float scaleX = bounds.width() / (float) composition.getBounds().width();
      float scaleY = bounds.height() / (float) composition.getBounds().height();

      renderingMatrix.preScale(scaleX, scaleY);
      renderingMatrix.preTranslate(bounds.left, bounds.top);
    }
    compositionLayer.draw(canvas, renderingMatrix, alpha);
  }

  /**
   * Software accelerated render path.
   * <p>
   * This draws the animation to an internally managed bitmap and then draws the bitmap to the original canvas.
   *
   * @see LottieAnimationView#setRenderMode(RenderMode)
   */
  private void renderAndDrawAsBitmap(Canvas originalCanvas, CompositionLayer compositionLayer) {
    if (composition == null || compositionLayer == null) {
      return;
    }
    ensureSoftwareRenderingObjectsInitialized();

    //noinspection deprecation
    originalCanvas.getMatrix(softwareRenderingOriginalCanvasMatrix);

    // Get the canvas clip bounds and map it to the coordinate space of canvas with it's current transform.
    originalCanvas.getClipBounds(canvasClipBounds);
    convertRect(canvasClipBounds, canvasClipBoundsRectF);
    softwareRenderingOriginalCanvasMatrix.mapRect(canvasClipBoundsRectF);
    convertRect(canvasClipBoundsRectF, canvasClipBounds);

    if (clipToCompositionBounds) {
      // Start with the intrinsic bounds. This will later be unioned with the clip bounds to find the
      // smallest possible render area.
      softwareRenderingTransformedBounds.set(0f, 0f, getIntrinsicWidth(), getIntrinsicHeight());
    } else {
      // Calculate the full bounds of the animation.
      compositionLayer.getBounds(softwareRenderingTransformedBounds, null, false);
    }
    // Transform the animation bounds to the bounds that they will render to on the canvas.
    softwareRenderingOriginalCanvasMatrix.mapRect(softwareRenderingTransformedBounds);

    // The bounds are usually intrinsicWidth x intrinsicHeight. If they are different, an external source is scaling this drawable.
    // This is how ImageView.ScaleType.FIT_XY works.
    Rect bounds = getBounds();
    float scaleX = bounds.width() / (float) getIntrinsicWidth();
    float scaleY = bounds.height() / (float) getIntrinsicHeight();
    scaleRect(softwareRenderingTransformedBounds, scaleX, scaleY);

    if (!ignoreCanvasClipBounds()) {
      softwareRenderingTransformedBounds.intersect(canvasClipBounds.left, canvasClipBounds.top, canvasClipBounds.right, canvasClipBounds.bottom);
    }

    int renderWidth = (int) Math.ceil(softwareRenderingTransformedBounds.width());
    int renderHeight = (int) Math.ceil(softwareRenderingTransformedBounds.height());

    if (renderWidth == 0 || renderHeight == 0) {
      return;
    }

    ensureSoftwareRenderingBitmap(renderWidth, renderHeight);

    if (isDirty) {
      renderingMatrix.set(softwareRenderingOriginalCanvasMatrix);
      renderingMatrix.preScale(scaleX, scaleY);
      // We want to render the smallest bitmap possible. If the animation doesn't start at the top left, we translate the canvas and shrink the
      // bitmap to avoid allocating and copying the empty space on the left and top. renderWidth and renderHeight take this into account.
      renderingMatrix.postTranslate(-softwareRenderingTransformedBounds.left, -softwareRenderingTransformedBounds.top);

      softwareRenderingBitmap.eraseColor(0);
      compositionLayer.draw(softwareRenderingCanvas, renderingMatrix, alpha);

      // Calculate the dst bounds.
      // We need to map the rendered coordinates back to the canvas's coordinates. To do so, we need to invert the transform
      // of the original canvas.
      // Take the bounds of the rendered animation and map them to the canvas's coordinates.
      // This is similar to the src rect above but the src bound may have a left and top offset.
      softwareRenderingOriginalCanvasMatrix.invert(softwareRenderingOriginalCanvasMatrixInverse);
      softwareRenderingOriginalCanvasMatrixInverse.mapRect(softwareRenderingDstBoundsRectF, softwareRenderingTransformedBounds);
      convertRect(softwareRenderingDstBoundsRectF, softwareRenderingDstBoundsRect);
    }

    softwareRenderingSrcBoundsRect.set(0, 0, renderWidth, renderHeight);
    originalCanvas.drawBitmap(softwareRenderingBitmap, softwareRenderingSrcBoundsRect, softwareRenderingDstBoundsRect, softwareRenderingPaint);
  }

  private void ensureSoftwareRenderingObjectsInitialized() {
    if (softwareRenderingCanvas != null) {
      return;
    }
    softwareRenderingCanvas = new Canvas();
    softwareRenderingTransformedBounds = new RectF();
    softwareRenderingOriginalCanvasMatrix = new Matrix();
    softwareRenderingOriginalCanvasMatrixInverse = new Matrix();
    canvasClipBounds = new Rect();
    canvasClipBoundsRectF = new RectF();
    softwareRenderingPaint = new LPaint();
    softwareRenderingSrcBoundsRect = new Rect();
    softwareRenderingDstBoundsRect = new Rect();
    softwareRenderingDstBoundsRectF = new RectF();
  }

  private void ensureSoftwareRenderingBitmap(int renderWidth, int renderHeight) {
    if (softwareRenderingBitmap == null ||
        softwareRenderingBitmap.getWidth() < renderWidth ||
        softwareRenderingBitmap.getHeight() < renderHeight) {
      // The bitmap is larger. We need to create a new one.
      softwareRenderingBitmap = Bitmap.createBitmap(renderWidth, renderHeight, Bitmap.Config.ARGB_8888);
      softwareRenderingCanvas.setBitmap(softwareRenderingBitmap);
      isDirty = true;
    } else if (softwareRenderingBitmap.getWidth() > renderWidth || softwareRenderingBitmap.getHeight() > renderHeight) {
      // The bitmap is smaller. Take subset of the original.
      softwareRenderingBitmap = Bitmap.createBitmap(softwareRenderingBitmap, 0, 0, renderWidth, renderHeight);
      softwareRenderingCanvas.setBitmap(softwareRenderingBitmap);
      isDirty = true;
    }
  }

  /**
   * Convert a RectF to a Rect
   */
  private void convertRect(RectF src, Rect dst) {
    dst.set(
        (int) Math.floor(src.left),
        (int) Math.floor(src.top),
        (int) Math.ceil(src.right),
        (int) Math.ceil(src.bottom)
    );
  }

  /**
   * Convert a Rect to a RectF
   */
  private void convertRect(Rect src, RectF dst) {
    dst.set(
        src.left,
        src.top,
        src.right,
        src.bottom);
  }

  private void scaleRect(RectF rect, float scaleX, float scaleY) {
    rect.set(
        rect.left * scaleX,
        rect.top * scaleY,
        rect.right * scaleX,
        rect.bottom * scaleY
    );
  }

  /**
   * When a View's parent has clipChildren set to false, it doesn't affect the clipBound
   * of its child canvases so we should explicitly check for it and draw the full animation
   * bounds instead.
   */
  private boolean ignoreCanvasClipBounds() {
    Callback callback = getCallback();
    if (!(callback instanceof View)) {
      // If the callback isn't a view then respect the canvas's clip bounds.
      return false;
    }
    ViewParent parent = ((View) callback).getParent();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && parent instanceof ViewGroup) {
      return !((ViewGroup) parent).getClipChildren();
    }
    // Unlikely to ever happen. If the callback is a View, its parent should be a ViewGroup.
    return false;
  }
}
