package com.airbnb.lottie;

import android.graphics.Path;
import android.graphics.PointF;

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

class AnimatableShapeValue extends BaseAnimatableValue<ShapeData, Path> {
  private final Path convertTypePath = new Path();
  private boolean closed;

  AnimatableShapeValue(JSONObject json, int frameRate, LottieComposition composition,
      boolean closed) {
    super(null, frameRate, composition, true);
    this.closed = closed;
    init(json);
  }

  @Override protected ShapeData valueFromObject(Object object, float scale) throws JSONException {
    JSONObject pointsData = null;
    if (object instanceof JSONArray) {
      try {
        Object firstObject = ((JSONArray) object).get(0);
        if (firstObject instanceof JSONObject && ((JSONObject) firstObject).has("v")) {
          pointsData = (JSONObject) firstObject;
        }
      } catch (JSONException e) {
        throw new IllegalStateException("Unable to get shape. " + object);
      }
    } else if (object instanceof JSONObject && ((JSONObject) object).has("v")) {
      pointsData = (JSONObject) object;
    }

    if (pointsData == null) {
      return null;
    }

    JSONArray pointsArray = null;
    JSONArray inTangents = null;
    JSONArray outTangents = null;
    try {
      pointsArray = pointsData.getJSONArray("v");
      inTangents = pointsData.getJSONArray("i");
      outTangents = pointsData.getJSONArray("o");

      if (pointsData.has("c")) {
        // Bodymovin < 4.4 uses "closed" one level up in the json so it is passed in to the
        // constructor.
        // Bodymovin 4.4+ has closed here.
        closed = pointsData.getBoolean("c");
      }
    } catch (JSONException e) {
      // Do nothing.
    }

    if (pointsArray == null || inTangents == null || outTangents == null ||
        pointsArray.length() != inTangents.length() ||
        pointsArray.length() != outTangents.length()) {
      throw new IllegalStateException("Unable to process points array or tangents. " + pointsData);
    }

    ShapeData shape = new ShapeData();

    PointF vertex = vertexAtIndex(0, pointsArray);
    vertex.x *= scale;
    vertex.y *= scale;
    shape.setInitialPoint(vertex);

    for (int i = 1; i < pointsArray.length(); i++) {
      vertex = vertexAtIndex(i, pointsArray);
      PointF previousVertex = vertexAtIndex(i - 1, pointsArray);
      PointF cp1 = vertexAtIndex(i - 1, outTangents);
      PointF cp2 = vertexAtIndex(i, inTangents);

      PointF shapeCp1 = MiscUtils.addPoints(previousVertex, cp1);
      PointF shapeCp2 = MiscUtils.addPoints(vertex, cp2);

      shapeCp1.x *= scale;
      shapeCp1.y *= scale;
      shapeCp2.x *= scale;
      shapeCp2.y *= scale;
      vertex.x *= scale;
      vertex.y *= scale;

      shape.addCurve(new CubicCurveData(shapeCp1, shapeCp2, vertex));
    }

    if (closed) {
      vertex = vertexAtIndex(0, pointsArray);
      PointF previousVertex = vertexAtIndex(pointsArray.length() - 1, pointsArray);
      PointF cp1 = vertexAtIndex(pointsArray.length() - 1, outTangents);
      PointF cp2 = vertexAtIndex(0, inTangents);

      PointF shapeCp1 = MiscUtils.addPoints(previousVertex, cp1);
      PointF shapeCp2 = MiscUtils.addPoints(vertex, cp2);

      if (scale != 1f) {
        shapeCp1.x *= scale;
        shapeCp1.y *= scale;
        shapeCp2.x *= scale;
        shapeCp2.y *= scale;
        vertex.x *= scale;
        vertex.y *= scale;
      }

      shape.addCurve(new CubicCurveData(shapeCp1, shapeCp2, vertex));
      shape.setClosed(true);
    }
    return shape;

  }

  private PointF vertexAtIndex(int idx, JSONArray points) {
    if (idx >= points.length()) {
      throw new IllegalArgumentException(
          "Invalid index " + idx + ". There are only " + points.length() + " points.");
    }

    try {
      JSONArray pointArray = points.getJSONArray(idx);
      Object x = pointArray.get(0);
      Object y = pointArray.get(1);
      return new PointF(
          x instanceof Double ? new Float((Double) x) : (int) x,
          y instanceof Double ? new Float((Double) y) : (int) y);
    } catch (JSONException e) {
      throw new IllegalArgumentException("Unable to get point.", e);
    }
  }

  @Override public KeyframeAnimation<Path> createAnimation() {
    if (!hasAnimation()) {
      return new StaticKeyframeAnimation<>(convertType(initialValue));
    }

    ShapeKeyframeAnimation animation =
        new ShapeKeyframeAnimation(duration, composition, keyTimes, keyValues, interpolators);
    animation.setStartDelay(delay);
    return animation;
  }

  @Override Path convertType(ShapeData shapeData) {
    convertTypePath.reset();
    MiscUtils.getPathFromData(shapeData, convertTypePath);
    return convertTypePath;
  }
}
