package com.airbnb.lottie.parser;

import android.graphics.PointF;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;

import androidx.annotation.Nullable;
import androidx.collection.SparseArrayCompat;
import androidx.core.view.animation.PathInterpolatorCompat;

import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.parser.moshi.JsonReader;
import com.airbnb.lottie.utils.MiscUtils;
import com.airbnb.lottie.utils.Utils;
import com.airbnb.lottie.value.Keyframe;

import java.io.IOException;
import java.lang.ref.WeakReference;

class KeyframeParser {
  /**
   * 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();
  private static SparseArrayCompat<WeakReference<Interpolator>> pathInterpolatorCache;

  static JsonReader.Options NAMES = JsonReader.Options.of(
      "t",  // 1
      "s",  // 2
      "e",  // 3
      "o",  // 4
      "i",  // 5
      "h",  // 6
      "to", // 7
      "ti"  // 8
  );
  static JsonReader.Options INTERPOLATOR_NAMES = JsonReader.Options.of(
      "x",  // 1
      "y"   // 2
  );

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

  @Nullable
  private static WeakReference<Interpolator> getInterpolator(int hash) {
    // This must be synchronized because get and put isn't thread safe because
    // SparseArrayCompat has to create new sized arrays sometimes.
    synchronized (KeyframeParser.class) {
      return pathInterpolatorCache().get(hash);
    }
  }

  private static void putInterpolator(int hash, WeakReference<Interpolator> interpolator) {
    // This must be synchronized because get and put isn't thread safe because
    // SparseArrayCompat has to create new sized arrays sometimes.
    synchronized (KeyframeParser.class) {
      pathInterpolatorCache.put(hash, interpolator);
    }
  }

  /**
   * @param multiDimensional When true, the keyframe interpolators can be independent for the X and Y axis.
   */
  static <T> Keyframe<T> parse(JsonReader reader, LottieComposition composition,
      float scale, ValueParser<T> valueParser, boolean animated, boolean multiDimensional) throws IOException {

    if (animated && multiDimensional) {
      return parseMultiDimensionalKeyframe(composition, reader, scale, valueParser);
    } else if (animated) {
      return parseKeyframe(composition, reader, scale, valueParser);
    } else {
      return parseStaticValue(reader, scale, valueParser);
    }
  }

  /**
   * beginObject will already be called on the keyframe so it can be differentiated with
   * a non animated value.
   */
  private static <T> Keyframe<T> parseKeyframe(LottieComposition composition, JsonReader reader,
      float scale, ValueParser<T> valueParser) throws IOException {
    PointF cp1 = null;
    PointF cp2 = null;

    float startFrame = 0;
    T startValue = null;
    T endValue = null;
    boolean hold = false;
    Interpolator interpolator = null;

    // Only used by PathKeyframe
    PointF pathCp1 = null;
    PointF pathCp2 = null;

    reader.beginObject();
    while (reader.hasNext()) {
      switch (reader.selectName(NAMES)) {
        case 0: // t
          startFrame = (float) reader.nextDouble();
          break;
        case 1: // s
          startValue = valueParser.parse(reader, scale);
          break;
        case 2: // e
          endValue = valueParser.parse(reader, scale);
          break;
        case 3: // o
          cp1 = JsonUtils.jsonToPoint(reader, 1f);
          break;
        case 4: // i
          cp2 = JsonUtils.jsonToPoint(reader, 1f);
          break;
        case 5: // h
          hold = reader.nextInt() == 1;
          break;
        case 6: // to
          pathCp1 = JsonUtils.jsonToPoint(reader, scale);
          break;
        case 7: // ti
          pathCp2 = JsonUtils.jsonToPoint(reader, scale);
          break;
        default:
          reader.skipValue();
      }
    }
    reader.endObject();

    if (hold) {
      endValue = startValue;
      // TODO: create a HoldInterpolator so progress changes don't invalidate.
      interpolator = LINEAR_INTERPOLATOR;
    } else if (cp1 != null && cp2 != null) {
      interpolator = interpolatorFor(cp1, cp2);
    } else {
      interpolator = LINEAR_INTERPOLATOR;
    }

    Keyframe<T> keyframe = new Keyframe<>(composition, startValue, endValue, interpolator, startFrame, null);

    keyframe.pathCp1 = pathCp1;
    keyframe.pathCp2 = pathCp2;
    return keyframe;
  }

  private static <T> Keyframe<T> parseMultiDimensionalKeyframe(LottieComposition composition, JsonReader reader,
      float scale, ValueParser<T> valueParser) throws IOException {
    PointF cp1 = null;
    PointF cp2 = null;

    PointF xCp1 = null;
    PointF xCp2 = null;
    PointF yCp1 = null;
    PointF yCp2 = null;

    float startFrame = 0;
    T startValue = null;
    T endValue = null;
    boolean hold = false;
    Interpolator interpolator = null;
    Interpolator xInterpolator = null;
    Interpolator yInterpolator = null;

    // Only used by PathKeyframe
    PointF pathCp1 = null;
    PointF pathCp2 = null;

    reader.beginObject();
    while (reader.hasNext()) {
      switch (reader.selectName(NAMES)) {
        case 0: // t
          startFrame = (float) reader.nextDouble();
          break;
        case 1: // s
          startValue = valueParser.parse(reader, scale);
          break;
        case 2: // e
          endValue = valueParser.parse(reader, scale);
          break;
        case 3: // o
          if (reader.peek() == JsonReader.Token.BEGIN_OBJECT) {
            reader.beginObject();
            float xCp1x = 0f;
            float xCp1y = 0f;
            float yCp1x = 0f;
            float yCp1y = 0f;
            while (reader.hasNext()) {
              switch (reader.selectName(INTERPOLATOR_NAMES)) {
                case 0: // x
                  if (reader.peek() == JsonReader.Token.NUMBER) {
                    xCp1x = (float) reader.nextDouble();
                    yCp1x = xCp1x;
                  } else {
                    reader.beginArray();
                    xCp1x = (float) reader.nextDouble();
                    yCp1x = (float) reader.nextDouble();
                    reader.endArray();
                  }
                  break;
                case 1: // y
                  if (reader.peek() == JsonReader.Token.NUMBER) {
                    xCp1y = (float) reader.nextDouble();
                    yCp1y = xCp1y;
                  } else {
                    reader.beginArray();
                    xCp1y = (float) reader.nextDouble();
                    yCp1y = (float) reader.nextDouble();
                    reader.endArray();
                  }
                  break;
                default:
                  reader.skipValue();
              }
            }
            xCp1 = new PointF(xCp1x, xCp1y);
            yCp1 = new PointF(yCp1x, yCp1y);
            reader.endObject();
          } else {
            cp1 = JsonUtils.jsonToPoint(reader, scale);
          }
          break;
        case 4: // i
          if (reader.peek() == JsonReader.Token.BEGIN_OBJECT) {
            reader.beginObject();
            float xCp2x = 0f;
            float xCp2y = 0f;
            float yCp2x = 0f;
            float yCp2y = 0f;
            while (reader.hasNext()) {
              switch (reader.selectName(INTERPOLATOR_NAMES)) {
                case 0: // x
                  if (reader.peek() == JsonReader.Token.NUMBER) {
                    xCp2x = (float) reader.nextDouble();
                    yCp2x = xCp2x;
                  } else {
                    reader.beginArray();
                    xCp2x = (float) reader.nextDouble();
                    yCp2x = (float) reader.nextDouble();
                    reader.endArray();
                  }
                  break;
                case 1: // y
                  if (reader.peek() == JsonReader.Token.NUMBER) {
                    xCp2y = (float) reader.nextDouble();
                    yCp2y = xCp2y;
                  } else {
                    reader.beginArray();
                    xCp2y = (float) reader.nextDouble();
                    yCp2y = (float) reader.nextDouble();
                    reader.endArray();
                  }
                  break;
                default:
                  reader.skipValue();
              }
            }
            xCp2 = new PointF(xCp2x, xCp2y);
            yCp2 = new PointF(yCp2x, yCp2y);
            reader.endObject();
          } else {
            cp2 = JsonUtils.jsonToPoint(reader, scale);
          }
          break;
        case 5: // h
          hold = reader.nextInt() == 1;
          break;
        case 6: // to
          pathCp1 = JsonUtils.jsonToPoint(reader, scale);
          break;
        case 7: // ti
          pathCp2 = JsonUtils.jsonToPoint(reader, scale);
          break;
        default:
          reader.skipValue();
      }
    }
    reader.endObject();

    if (hold) {
      endValue = startValue;
      // TODO: create a HoldInterpolator so progress changes don't invalidate.
      interpolator = LINEAR_INTERPOLATOR;
    } else if (cp1 != null && cp2 != null) {
      interpolator = interpolatorFor(cp1, cp2);
    } else if (xCp1 != null && yCp1 != null && xCp2 != null && yCp2 != null) {
      xInterpolator = interpolatorFor(xCp1, xCp2);
      yInterpolator = interpolatorFor(yCp1, yCp2);
    } else {
      interpolator = LINEAR_INTERPOLATOR;
    }

    Keyframe<T> keyframe;
    if (xInterpolator != null && yInterpolator != null) {
      keyframe = new Keyframe<>(composition, startValue, endValue, xInterpolator, yInterpolator, startFrame, null);
    } else {
      keyframe = new Keyframe<>(composition, startValue, endValue, interpolator, startFrame, null);
    }

    keyframe.pathCp1 = pathCp1;
    keyframe.pathCp2 = pathCp2;
    return keyframe;
  }

  private static Interpolator interpolatorFor(PointF cp1, PointF cp2) {
    Interpolator interpolator = null;
    cp1.x = MiscUtils.clamp(cp1.x, -1f, 1f);
    cp1.y = MiscUtils.clamp(cp1.y, -MAX_CP_VALUE, MAX_CP_VALUE);
    cp2.x = MiscUtils.clamp(cp2.x, -1f, 1f);
    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 = getInterpolator(hash);
    if (interpolatorRef != null) {
      interpolator = interpolatorRef.get();
    }
    if (interpolatorRef == null || interpolator == null) {
      try {
        interpolator = PathInterpolatorCompat.create(cp1.x, cp1.y, cp2.x, cp2.y);
      } catch (IllegalArgumentException e) {
        if ("The Path cannot loop back on itself.".equals(e.getMessage())) {
          // If a control point extends beyond the previous/next point then it will cause the value of the interpolator to no
          // longer monotonously increase. This clips the control point bounds to prevent that from happening.
          // NOTE: this will make the rendered animation behave slightly differently than the original.
          interpolator = PathInterpolatorCompat.create(Math.min(cp1.x, 1f), cp1.y, Math.max(cp2.x, 0f), cp2.y);
        } else {
          // We failed to create the interpolator. Fall back to linear.
          interpolator = new LinearInterpolator();
        }
      }
      try {
        putInterpolator(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.
      }
    }
    return interpolator;
  }

  private static <T> Keyframe<T> parseStaticValue(JsonReader reader,
      float scale, ValueParser<T> valueParser) throws IOException {
    T value = valueParser.parse(reader, scale);
    return new Keyframe<>(value);
  }
}
