package com.airbnb.lottie.animation;

import android.graphics.PointF;
import android.support.annotation.FloatRange;
import android.support.annotation.Nullable;
import android.support.v4.util.SparseArrayCompat;
import android.support.v4.view.animation.PathInterpolatorCompat;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;

import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.model.animatable.AnimatableValue;
import com.airbnb.lottie.utils.JsonUtils;
import com.airbnb.lottie.utils.MiscUtils;
import com.airbnb.lottie.utils.Utils;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Keyframe<T> {
  /**
   * Some animations get exported with insane cp values in the tens of thousands.
   * PathInterpolator fails to create the interpolator in those cases and hangs.
   * Clamping the cp helps prevent that.
   */
  private static final float MAX_CP_VALUE = 100;
  private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();

  /**
   * The json doesn't include end frames. The data can be taken from the start frame of the next
   * keyframe though.
   */
  public static void setEndFrames(List<? extends Keyframe<?>> keyframes) {
    int size = keyframes.size();
    for (int i = 0; i < size - 1; i++) {
      // In the json, the keyframes only contain their starting frame.
      keyframes.get(i).endFrame = keyframes.get(i + 1).startFrame;
    }
    Keyframe<?> lastKeyframe = keyframes.get(size - 1);
    if (lastKeyframe.startValue == null) {
      // The only purpose the last keyframe has is to provide the end frame of the previous
      // keyframe.
      //noinspection SuspiciousMethodCalls
      keyframes.remove(lastKeyframe);
    }
  }


  private final LottieComposition composition;
  @Nullable public final T startValue;
  @Nullable public final T endValue;
  @Nullable public final Interpolator interpolator;
  public final float startFrame;
  @Nullable public Float endFrame;

  private float startProgress = Float.MIN_VALUE;
  private float endProgress = Float.MIN_VALUE;

  public Keyframe(LottieComposition composition, @Nullable T startValue, @Nullable T endValue,
      @Nullable Interpolator interpolator, float startFrame, @Nullable Float endFrame) {
    this.composition = composition;
    this.startValue = startValue;
    this.endValue = endValue;
    this.interpolator = interpolator;
    this.startFrame = startFrame;
    this.endFrame = endFrame;
  }

  public float getStartProgress() {
    if (startProgress == Float.MIN_VALUE) {
      startProgress = (startFrame  - composition.getStartFrame()) / composition.getDurationFrames();
    }
    return startProgress;
  }

  public float getEndProgress() {
    if (endProgress == Float.MIN_VALUE) {
      if (endFrame == null) {
        endProgress = 1f;
      } else {
        float startProgress = getStartProgress();
        float durationFrames = endFrame - startFrame;
        float durationProgress = durationFrames / composition.getDurationFrames();
        endProgress = startProgress + durationProgress;
      }
    }
    return endProgress;
  }

  public boolean isStatic() {
    return interpolator == null;
  }

  public boolean containsProgress(@FloatRange(from = 0f, to = 1f) float progress) {
    return progress >= getStartProgress() && progress <= getEndProgress();
  }

  @Override public String toString() {
    return "Keyframe{" + "startValue=" + startValue +
        ", endValue=" + endValue +
        ", startFrame=" + startFrame +
        ", endFrame=" + endFrame +
        ", interpolator=" + interpolator +
        '}';
  }

  public static class Factory {
    private static SparseArrayCompat<WeakReference<Interpolator>> pathInterpolatorCache;

    // https://github.com/airbnb/lottie-android/issues/464
    private static SparseArrayCompat<WeakReference<Interpolator>> pathInterpolatorCache() {
      if (pathInterpolatorCache == null) {
        pathInterpolatorCache = new SparseArrayCompat<>();
      }
      return pathInterpolatorCache;
    }

    private Factory() {
    }

    public static <T> Keyframe<T> newInstance(JSONObject json, LottieComposition composition, float scale,
        AnimatableValue.Factory<T> valueFactory) {
      PointF cp1 = null;
      PointF cp2 = null;
      float startFrame = 0;
      T startValue = null;
      T endValue = null;
      Interpolator interpolator = null;

      if (json.has("t")) {
        startFrame = (float) json.optDouble("t", 0);
        Object startValueJson = json.opt("s");
        if (startValueJson != null) {
          startValue = valueFactory.valueFromObject(startValueJson, scale);
        }

        Object endValueJson = json.opt("e");
        if (endValueJson != null) {
          endValue = valueFactory.valueFromObject(endValueJson, scale);
        }

        JSONObject cp1Json = json.optJSONObject("o");
        JSONObject cp2Json = json.optJSONObject("i");
        if (cp1Json != null && cp2Json != null) {
          cp1 = JsonUtils.pointFromJsonObject(cp1Json, scale);
          cp2 = JsonUtils.pointFromJsonObject(cp2Json, scale);
        }

        boolean hold = json.optInt("h", 0) == 1;

        if (hold) {
          endValue = startValue;
          // TODO: create a HoldInterpolator so progress changes don't invalidate.
          interpolator = LINEAR_INTERPOLATOR;
        } else if (cp1 != null) {
          cp1.x = MiscUtils.clamp(cp1.x, -scale, scale);
          cp1.y = MiscUtils.clamp(cp1.y, -MAX_CP_VALUE, MAX_CP_VALUE);
          cp2.x = MiscUtils.clamp(cp2.x, -scale, scale);
          cp2.y = MiscUtils.clamp(cp2.y, -MAX_CP_VALUE, MAX_CP_VALUE);
          int hash = Utils.hashFor(cp1.x, cp1.y, cp2.x, cp2.y);
          WeakReference<Interpolator> interpolatorRef = pathInterpolatorCache().get(hash);
          if (interpolatorRef != null) {
            interpolator = interpolatorRef.get();
          }
          if (interpolatorRef == null || interpolator == null) {
            interpolator = PathInterpolatorCompat.create(
                cp1.x / scale, cp1.y / scale, cp2.x / scale, cp2.y / scale);
            try {
              pathInterpolatorCache().put(hash, new WeakReference<>(interpolator));
            } catch (ArrayIndexOutOfBoundsException e) {
              // It is not clear why but SparseArrayCompat sometimes fails with this:
              //     https://github.com/airbnb/lottie-android/issues/452
              // Because this is not a critical operation, we can safely just ignore it.
              // I was unable to repro this to attempt a proper fix.
            }
          }

        } else {
          interpolator = LINEAR_INTERPOLATOR;
        }
      } else {
        startValue = valueFactory.valueFromObject(json, scale);
        endValue = startValue;
      }
      return new Keyframe<>(composition, startValue, endValue, interpolator, startFrame, null);
    }

    public static <T> List<Keyframe<T>> parseKeyframes(JSONArray json,
        LottieComposition composition,
        float scale, AnimatableValue.Factory<T> valueFactory) {
      int length = json.length();
      if (length == 0) {
        return Collections.emptyList();
      }
      List<Keyframe<T>> keyframes = new ArrayList<>();
      for (int i = 0; i < length; i++) {
        keyframes.add(Keyframe.Factory.newInstance(json.optJSONObject(i), composition, scale,
            valueFactory));
      }

      setEndFrames(keyframes);
      return keyframes;
    }
  }
}
