package com.airbnb.lottie.utils;

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

import androidx.annotation.FloatRange;

import com.airbnb.lottie.animation.content.KeyPathElementContent;
import com.airbnb.lottie.model.CubicCurveData;
import com.airbnb.lottie.model.KeyPath;
import com.airbnb.lottie.model.content.ShapeData;

import java.util.List;

public class MiscUtils {
  private static PointF pathFromDataCurrentPoint = new PointF();

  public static PointF addPoints(PointF p1, PointF p2) {
    return new PointF(p1.x + p2.x, p1.y + p2.y);
  }

  public static void getPathFromData(ShapeData shapeData, Path outPath) {
    outPath.reset();
    PointF initialPoint = shapeData.getInitialPoint();
    outPath.moveTo(initialPoint.x, initialPoint.y);
    pathFromDataCurrentPoint.set(initialPoint.x, initialPoint.y);
    for (int i = 0; i < shapeData.getCurves().size(); i++) {
      CubicCurveData curveData = shapeData.getCurves().get(i);
      PointF cp1 = curveData.getControlPoint1();
      PointF cp2 = curveData.getControlPoint2();
      PointF vertex = curveData.getVertex();

      if (cp1.equals(pathFromDataCurrentPoint) && cp2.equals(vertex)) {
        // On some phones like Samsung phones, zero valued control points can cause artifacting.
        // https://github.com/airbnb/lottie-android/issues/275
        //
        // This does its best to add a tiny value to the vertex without affecting the final
        // animation as much as possible.
        // outPath.rMoveTo(0.01f, 0.01f);
        outPath.lineTo(vertex.x, vertex.y);
      } else {
        outPath.cubicTo(cp1.x, cp1.y, cp2.x, cp2.y, vertex.x, vertex.y);
      }
      pathFromDataCurrentPoint.set(vertex.x, vertex.y);
    }
    if (shapeData.isClosed()) {
      outPath.close();
    }
  }

  public static float lerp(float a, float b, @FloatRange(from = 0f, to = 1f) float percentage) {
    return a + percentage * (b - a);
  }

  public static double lerp(double a, double b, @FloatRange(from = 0f, to = 1f) double percentage) {
    return a + percentage * (b - a);
  }

  public static int lerp(int a, int b, @FloatRange(from = 0f, to = 1f) float percentage) {
    return (int) (a + percentage * (b - a));
  }

  static int floorMod(float x, float y) {
    return floorMod((int) x, (int) y);
  }

  private static int floorMod(int x, int y) {
    return x - y * floorDiv(x, y);
  }

  private static int floorDiv(int x, int y) {
    int r = x / y;
    boolean sameSign = (x ^ y) >= 0;
    int mod = x % y;
    if (!sameSign && mod != 0) {
      r--;
    }
    return r;
  }

  public static int clamp(int number, int min, int max) {
    return Math.max(min, Math.min(max, number));
  }

  public static float clamp(float number, float min, float max) {
    return Math.max(min, Math.min(max, number));
  }

  public static double clamp(double number, double min, double max) {
    return Math.max(min, Math.min(max, number));
  }

  public static boolean contains(float number, float rangeMin, float rangeMax) {
    return number >= rangeMin && number <= rangeMax;
  }

  /**
   * Helper method for any {@link KeyPathElementContent} that will check if the content
   * fully matches the keypath then will add itself as the final key, resolve it, and add
   * it to the accumulator list.
   * <p>
   * Any {@link KeyPathElementContent} should call through to this as its implementation of
   * {@link KeyPathElementContent#resolveKeyPath(KeyPath, int, List, KeyPath)}.
   */
  public static void resolveKeyPath(KeyPath keyPath, int depth, List<KeyPath> accumulator,
      KeyPath currentPartialKeyPath, KeyPathElementContent content) {
    if (keyPath.fullyResolvesTo(content.getName(), depth)) {
      currentPartialKeyPath = currentPartialKeyPath.addKey(content.getName());
      accumulator.add(currentPartialKeyPath.resolve(content));
    }
  }
}
