package main

import "core:math"
import "core:math/ease"
import "core:math/linalg"
import "core:slice"


Tween :: struct {
	ptr: ^f32,
	from: f32,
	to: f32,
	time: f32,
	duration: f32,
	ease_type: ease.Ease,
	active: bool,
	finished: proc(data: rawptr),
	data: rawptr
}


tweens : [dynamic]^Tween


tween_clean :: proc() {
	for tween, i in tweens {
		free(tween)
	}
}

tween_to :: proc(
		value: ^f32, to: f32, duration: f32,
		ease: ease.Ease = ease.Ease.Quartic_In_Out,
		data: rawptr = nil,
		callback: proc(data: rawptr) = nil
		) -> ^Tween {

	tween := new(Tween) 
	tween.ptr = value
	tween.from = value^
	tween.to = to
	tween.duration = duration
	tween.ease_type = ease
	tween.active = true
	tween.data = data
	tween.finished = callback

	append(&tweens, tween)
	return tween
}

tween_cancel :: proc(t: ^Tween) {
	t.active = false
}

tweens_process :: proc(delta: f32) {
	#reverse for tween, i in tweens {

		tween.time += delta
		p := clamp(tween.time / tween.duration, 0, 1)

		val := ease.ease(tween.ease_type, p)
		if tween.ptr != nil {
			tween.ptr^ = math.lerp(tween.from, tween.to, val)
		} else {
			tween.active = false
		}

		if tween.time >= tween.duration {
			tween.active = false
			if tween.finished != nil {
				tween.finished(tween.data)
			}
		}
		if !tween.active {
			free(tween)
			unordered_remove(&tweens, i)
		}
	}
}
