package speiger.src.coreengine.rendering.gui.animation;

import speiger.src.collections.objects.functions.consumer.ObjectFloatConsumer;
import speiger.src.collections.objects.functions.function.ToFloatFunction;
import speiger.src.coreengine.rendering.gui.animation.GuiAnimation.Target;
import speiger.src.coreengine.rendering.gui.components.base.GuiComponent;
import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox;

public class GuiAnimationSnapshot implements ToFloatFunction<Target>, ObjectFloatConsumer<Target> {
	final GuiAnimator animator;
	final float x;
	final float y;
	final float width;
	final float height;
	final float scale;
	final boolean looping;
	float progress;
	int loops;
	
	public GuiAnimationSnapshot(GuiAnimator animator, IGuiBox box, boolean looping) {
		this(animator, box.getBaseX(), box.getBaseY(), box.getBaseWidth(), box.getBaseHeight(), box.getBaseScale(), looping);
	}
	
	public GuiAnimationSnapshot(GuiAnimator animator, float x, float y, float width, float height, float scale, boolean looping) {
		this.animator = animator;
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		this.scale = scale;
		this.looping = looping;
	}
	
	@Override
	public float applyAsFloat(Target k) {
		return switch(k) {
			case X -> x;
			case Y -> y;
			case WIDTH -> width;
			case HEIGHT -> height;
			case SCALE -> scale;
			default -> 0F;
		};
	}
	
	@Override
	public void accept(Target k, float v) {
		switch(k) {
			case X -> animator.accept(k, v - x);
			case Y -> animator.accept(k, v - y);
			case WIDTH -> animator.accept(k, v - width);
			case HEIGHT -> animator.accept(k, v - height);
			case SCALE -> animator.accept(k, v / scale);
		}
	}
	
	public int loops() {
		return loops;
	}
	
	public GuiAnimationSnapshot applyDifference(GuiComponent component) {
		for(Target target : Target.values()) {
			animator.accept(target, applyAsFloat(target) - target.get(component));
		}
		return this;
	}
	
	public boolean update(GuiAnimation animation, float partialTime) {
		progress += partialTime;
		animation.apply(this, this, Math.min(progress, animation.duration()));
		if(progress >= animation.duration()) {
			if(!looping) return true;
			progress = 0F;
			loops++;
		}
		return false;
	}
}