package wtf.opal.utility.render.animation;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;

@Environment(EnvType.CLIENT)
public final class Animation {
   private Easing easing;
   private long duration;
   private long millis;
   private long startTime;
   private float startValue;
   private float destinationValue;
   private float value;
   private boolean finished;

   public Animation(Easing easing, long duration) {
      this.easing = easing;
      this.startTime = System.currentTimeMillis();
      this.duration = duration;
   }

   public void run(float destinationValue) {
      this.millis = System.currentTimeMillis();
      if (this.destinationValue != destinationValue) {
         this.destinationValue = destinationValue;
         this.reset();
      } else {
         this.finished = this.millis - this.duration > this.startTime || this.value == destinationValue;
         if (this.finished) {
            this.value = destinationValue;
            return;
         }
      }

      float var2 = this.duration == 0L ? 1.0F : this.easing.getFunction().apply(this.getProgress());
      if (this.duration == 0L) {
         this.value = destinationValue;
      } else if (this.value > destinationValue) {
         this.value = this.startValue - (this.startValue - destinationValue) * var2;
      } else {
         this.value = this.startValue + (destinationValue - this.startValue) * var2;
      }

      if (Float.isNaN(this.value) || !Float.isFinite(this.value)) {
         this.value = destinationValue;
      }
   }

   public float getProgress() {
      return (float)(System.currentTimeMillis() - this.startTime) / (float)this.duration;
   }

   public void reset() {
      this.startTime = System.currentTimeMillis();
      this.startValue = this.value;
      this.finished = false;
   }

   public long getDuration() {
      return this.duration;
   }

   public void setDuration(long duration) {
      this.duration = duration;
   }

   public Easing getEasing() {
      return this.easing;
   }

   public void setEasing(Easing easing) {
      if (easing != null && this.easing != easing) {
         this.easing = easing;
         this.reset();
      }
   }

   public void setMillis(long millis) {
      this.millis = millis;
   }

   public long getMillis() {
      return this.millis;
   }

   public float getValue() {
      return this.value;
   }

   public void setValue(float value) {
      this.value = value;
   }

   public void setStartValue(float startValue) {
      this.startValue = startValue;
      this.value = startValue;
   }

   public float getStartValue() {
      return this.startValue;
   }

   public boolean isFinished() {
      return this.finished;
   }

   public void setFinished(boolean finished) {
      this.finished = finished;
   }
}
