package com.airbnb.lottie.animation.content;

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

import androidx.annotation.Nullable;

import com.airbnb.lottie.LottieDrawable;
import com.airbnb.lottie.LottieProperty;
import com.airbnb.lottie.animation.keyframe.BaseKeyframeAnimation;
import com.airbnb.lottie.model.KeyPath;
import com.airbnb.lottie.model.content.PolystarShape;
import com.airbnb.lottie.model.content.ShapeTrimPath;
import com.airbnb.lottie.model.layer.BaseLayer;
import com.airbnb.lottie.utils.MiscUtils;
import com.airbnb.lottie.value.LottieValueCallback;

import java.util.List;

public class PolystarContent
    implements PathContent, BaseKeyframeAnimation.AnimationListener, KeyPathElementContent {
  /**
   * This was empirically derived by creating polystars, converting them to
   * curves, and calculating a scale factor.
   * It works best for polygons and stars with 3 points and needs more
   * work otherwise.
   */
  private static final float POLYSTAR_MAGIC_NUMBER = .47829f;
  private static final float POLYGON_MAGIC_NUMBER = .25f;
  private final Path path = new Path();

  private final String name;
  private final LottieDrawable lottieDrawable;
  private final PolystarShape.Type type;
  private final boolean hidden;
  private final BaseKeyframeAnimation<?, Float> pointsAnimation;
  private final BaseKeyframeAnimation<?, PointF> positionAnimation;
  private final BaseKeyframeAnimation<?, Float> rotationAnimation;
  @Nullable private final BaseKeyframeAnimation<?, Float> innerRadiusAnimation;
  private final BaseKeyframeAnimation<?, Float> outerRadiusAnimation;
  @Nullable private final BaseKeyframeAnimation<?, Float> innerRoundednessAnimation;
  private final BaseKeyframeAnimation<?, Float> outerRoundednessAnimation;

  private CompoundTrimPathContent trimPaths = new CompoundTrimPathContent();
  private boolean isPathValid;

  public PolystarContent(LottieDrawable lottieDrawable, BaseLayer layer,
      PolystarShape polystarShape) {
    this.lottieDrawable = lottieDrawable;

    name = polystarShape.getName();
    type = polystarShape.getType();
    hidden = polystarShape.isHidden();
    pointsAnimation = polystarShape.getPoints().createAnimation();
    positionAnimation = polystarShape.getPosition().createAnimation();
    rotationAnimation = polystarShape.getRotation().createAnimation();
    outerRadiusAnimation = polystarShape.getOuterRadius().createAnimation();
    outerRoundednessAnimation = polystarShape.getOuterRoundedness().createAnimation();
    if (type == PolystarShape.Type.STAR) {
      innerRadiusAnimation = polystarShape.getInnerRadius().createAnimation();
      innerRoundednessAnimation = polystarShape.getInnerRoundedness().createAnimation();
    } else {
      innerRadiusAnimation = null;
      innerRoundednessAnimation = null;
    }

    layer.addAnimation(pointsAnimation);
    layer.addAnimation(positionAnimation);
    layer.addAnimation(rotationAnimation);
    layer.addAnimation(outerRadiusAnimation);
    layer.addAnimation(outerRoundednessAnimation);
    if (type == PolystarShape.Type.STAR) {
      layer.addAnimation(innerRadiusAnimation);
      layer.addAnimation(innerRoundednessAnimation);
    }

    pointsAnimation.addUpdateListener(this);
    positionAnimation.addUpdateListener(this);
    rotationAnimation.addUpdateListener(this);
    outerRadiusAnimation.addUpdateListener(this);
    outerRoundednessAnimation.addUpdateListener(this);
    if (type == PolystarShape.Type.STAR) {
      innerRadiusAnimation.addUpdateListener(this);
      innerRoundednessAnimation.addUpdateListener(this);
    }
  }

  @Override public void onValueChanged() {
    invalidate();
  }

  private void invalidate() {
    isPathValid = false;
    lottieDrawable.invalidateSelf();
  }

  @Override public void setContents(List<Content> contentsBefore, List<Content> contentsAfter) {
    for (int i = 0; i < contentsBefore.size(); i++) {
      Content content = contentsBefore.get(i);
      if (content instanceof TrimPathContent &&
          ((TrimPathContent) content).getType() == ShapeTrimPath.Type.SIMULTANEOUSLY) {
        TrimPathContent trimPath = (TrimPathContent) content;
        trimPaths.addTrimPath(trimPath);
        trimPath.addListener(this);
      }
    }
  }

  @Override public Path getPath() {
    if (isPathValid) {
      return path;
    }

    path.reset();

    if (hidden) {
      isPathValid = true;
      return path;
    }

    switch (type) {
      case STAR:
        createStarPath();
        break;
      case POLYGON:
        createPolygonPath();
        break;
    }

    path.close();

    trimPaths.apply(path);

    isPathValid = true;
    return path;
  }

  @Override public String getName() {
    return name;
  }

  private void createStarPath() {
    float points = pointsAnimation.getValue();
    double currentAngle = rotationAnimation == null ? 0f : rotationAnimation.getValue();
    // Start at +y instead of +x
    currentAngle -= 90;
    // convert to radians
    currentAngle = Math.toRadians(currentAngle);
    // adjust current angle for partial points
    float anglePerPoint = (float) (2 * Math.PI / points);
    float halfAnglePerPoint = anglePerPoint / 2.0f;
    float partialPointAmount = points - (int) points;
    if (partialPointAmount != 0) {
      currentAngle += halfAnglePerPoint * (1f - partialPointAmount);
    }

    float outerRadius = outerRadiusAnimation.getValue();
    //noinspection ConstantConditions
    float innerRadius = innerRadiusAnimation.getValue();

    float innerRoundedness = 0f;
    if (innerRoundednessAnimation != null) {
      innerRoundedness = innerRoundednessAnimation.getValue() / 100f;
    }
    float outerRoundedness = 0f;
    if (outerRoundednessAnimation != null) {
      outerRoundedness = outerRoundednessAnimation.getValue() / 100f;
    }

    float x;
    float y;
    float previousX;
    float previousY;
    float partialPointRadius = 0;
    if (partialPointAmount != 0) {
      partialPointRadius = innerRadius + partialPointAmount * (outerRadius - innerRadius);
      x = (float) (partialPointRadius * Math.cos(currentAngle));
      y = (float) (partialPointRadius * Math.sin(currentAngle));
      path.moveTo(x, y);
      currentAngle += anglePerPoint * partialPointAmount / 2f;
    } else {
      x = (float) (outerRadius * Math.cos(currentAngle));
      y = (float) (outerRadius * Math.sin(currentAngle));
      path.moveTo(x, y);
      currentAngle += halfAnglePerPoint;
    }

    // True means the line will go to outer radius. False means inner radius.
    boolean longSegment = false;
    double numPoints = Math.ceil(points) * 2;
    for (int i = 0; i < numPoints; i++) {
      float radius = longSegment ? outerRadius : innerRadius;
      float dTheta = halfAnglePerPoint;
      if (partialPointRadius != 0 && i == numPoints - 2) {
        dTheta = anglePerPoint * partialPointAmount / 2f;
      }
      if (partialPointRadius != 0 && i == numPoints - 1) {
        radius = partialPointRadius;
      }
      previousX = x;
      previousY = y;
      x = (float) (radius * Math.cos(currentAngle));
      y = (float) (radius * Math.sin(currentAngle));

      if (innerRoundedness == 0 && outerRoundedness == 0) {
        path.lineTo(x, y);
      } else {
        float cp1Theta = (float) (Math.atan2(previousY, previousX) - Math.PI / 2f);
        float cp1Dx = (float) Math.cos(cp1Theta);
        float cp1Dy = (float) Math.sin(cp1Theta);

        float cp2Theta = (float) (Math.atan2(y, x) - Math.PI / 2f);
        float cp2Dx = (float) Math.cos(cp2Theta);
        float cp2Dy = (float) Math.sin(cp2Theta);

        float cp1Roundedness = longSegment ? innerRoundedness : outerRoundedness;
        float cp2Roundedness = longSegment ? outerRoundedness : innerRoundedness;
        float cp1Radius = longSegment ? innerRadius : outerRadius;
        float cp2Radius = longSegment ? outerRadius : innerRadius;

        float cp1x = cp1Radius * cp1Roundedness * POLYSTAR_MAGIC_NUMBER * cp1Dx;
        float cp1y = cp1Radius * cp1Roundedness * POLYSTAR_MAGIC_NUMBER * cp1Dy;
        float cp2x = cp2Radius * cp2Roundedness * POLYSTAR_MAGIC_NUMBER * cp2Dx;
        float cp2y = cp2Radius * cp2Roundedness * POLYSTAR_MAGIC_NUMBER * cp2Dy;
        if (partialPointAmount != 0) {
          if (i == 0) {
            cp1x *= partialPointAmount;
            cp1y *= partialPointAmount;
          } else if (i == numPoints - 1) {
            cp2x *= partialPointAmount;
            cp2y *= partialPointAmount;
          }
        }

        path.cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y, x, y);
      }

      currentAngle += dTheta;
      longSegment = !longSegment;
    }


    PointF position = positionAnimation.getValue();
    path.offset(position.x, position.y);
    path.close();
  }

  private void createPolygonPath() {
    int points = (int) Math.floor(pointsAnimation.getValue());
    double currentAngle = rotationAnimation == null ? 0f : rotationAnimation.getValue();
    // Start at +y instead of +x
    currentAngle -= 90;
    // convert to radians
    currentAngle = Math.toRadians(currentAngle);
    // adjust current angle for partial points
    float anglePerPoint = (float) (2 * Math.PI / points);

    float roundedness = outerRoundednessAnimation.getValue() / 100f;
    float radius = outerRadiusAnimation.getValue();
    float x;
    float y;
    float previousX;
    float previousY;
    x = (float) (radius * Math.cos(currentAngle));
    y = (float) (radius * Math.sin(currentAngle));
    path.moveTo(x, y);
    currentAngle += anglePerPoint;

    double numPoints = Math.ceil(points);
    for (int i = 0; i < numPoints; i++) {
      previousX = x;
      previousY = y;
      x = (float) (radius * Math.cos(currentAngle));
      y = (float) (radius * Math.sin(currentAngle));

      if (roundedness != 0) {
        float cp1Theta = (float) (Math.atan2(previousY, previousX) - Math.PI / 2f);
        float cp1Dx = (float) Math.cos(cp1Theta);
        float cp1Dy = (float) Math.sin(cp1Theta);

        float cp2Theta = (float) (Math.atan2(y, x) - Math.PI / 2f);
        float cp2Dx = (float) Math.cos(cp2Theta);
        float cp2Dy = (float) Math.sin(cp2Theta);

        float cp1x = radius * roundedness * POLYGON_MAGIC_NUMBER * cp1Dx;
        float cp1y = radius * roundedness * POLYGON_MAGIC_NUMBER * cp1Dy;
        float cp2x = radius * roundedness * POLYGON_MAGIC_NUMBER * cp2Dx;
        float cp2y = radius * roundedness * POLYGON_MAGIC_NUMBER * cp2Dy;
        path.cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y, x, y);
      } else {
        path.lineTo(x, y);
      }

      currentAngle += anglePerPoint;
    }

    PointF position = positionAnimation.getValue();
    path.offset(position.x, position.y);
    path.close();
  }

  @Override public void resolveKeyPath(
      KeyPath keyPath, int depth, List<KeyPath> accumulator, KeyPath currentPartialKeyPath) {
    MiscUtils.resolveKeyPath(keyPath, depth, accumulator, currentPartialKeyPath, this);
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> void addValueCallback(T property, @Nullable LottieValueCallback<T> callback) {
    if (property == LottieProperty.POLYSTAR_POINTS) {
      pointsAnimation.setValueCallback((LottieValueCallback<Float>) callback);
    } else if (property == LottieProperty.POLYSTAR_ROTATION) {
      rotationAnimation.setValueCallback((LottieValueCallback<Float>) callback);
    } else if (property == LottieProperty.POSITION) {
      positionAnimation.setValueCallback((LottieValueCallback<PointF>) callback);
    } else if (property == LottieProperty.POLYSTAR_INNER_RADIUS && innerRadiusAnimation != null) {
      innerRadiusAnimation.setValueCallback((LottieValueCallback<Float>) callback);
    } else if (property == LottieProperty.POLYSTAR_OUTER_RADIUS) {
      outerRadiusAnimation.setValueCallback((LottieValueCallback<Float>) callback);
    } else if (property == LottieProperty.POLYSTAR_INNER_ROUNDEDNESS && innerRoundednessAnimation != null) {
      innerRoundednessAnimation.setValueCallback((LottieValueCallback<Float>) callback);
    } else if (property == LottieProperty.POLYSTAR_OUTER_ROUNDEDNESS) {
      outerRoundednessAnimation.setValueCallback((LottieValueCallback<Float>) callback);
    }
  }
}
