#include "bones/BoneAnimationSequence.h"

#include <math.h>

#include "bones/Skeleton.h"

BoneAnimationSequence * BoneAnimationSequence_create(Atom name, Skeleton * skeleton) {
	BoneAnimationSequence * self;
	
	self = malloc(sizeof(BoneAnimationSequence));
	BoneAnimationSequence_init(self, name, skeleton);
	return self;
}

void BoneAnimationSequence_init(BoneAnimationSequence * self, Atom name, Skeleton * skeleton) {
	self->name = name;
	self->skeleton = skeleton;
	self->numberOfKeyframes = 0;
	self->keyframes = NULL;
	
	self->dispose = BoneAnimationSequence_dispose;
	self->getDuration = BoneAnimationSequence_getDuration;
	self->keyframeIndexForTime = BoneAnimationSequence_keyframeIndexForTime;
	self->timeForKeyframeIndex = BoneAnimationSequence_timeForKeyframeIndex;
}

void BoneAnimationSequence_dispose(void * selfPtr) {
	BoneAnimationSequence * self = selfPtr;
	unsigned int keyframeIndex;
	
	for (keyframeIndex = 0; keyframeIndex < self->numberOfKeyframes; keyframeIndex++) {
		free(self->keyframes[keyframeIndex].boneTransforms);
	}
	free(self->keyframes);
	free(self);
}

float BoneAnimationSequence_getDuration(void * selfPtr) {
	BoneAnimationSequence * self = selfPtr;
	unsigned int keyframeIndex;
	float duration = 0.0f;
	
	for (keyframeIndex = 0; keyframeIndex < self->numberOfKeyframes; keyframeIndex++) {
		duration += self->keyframes[keyframeIndex].duration;
	}
	return duration;
}

int BoneAnimationSequence_keyframeIndexForTime(void * selfPtr, float time) {
	BoneAnimationSequence * self = selfPtr;
	unsigned int keyframeIndex;
	float accumulatedTime = 0.0f;
	
	time = fmod(time, self->getDuration(self));
	for (keyframeIndex = 0; keyframeIndex < self->numberOfKeyframes; keyframeIndex++) {
		accumulatedTime += self->keyframes[keyframeIndex].duration;
		if (accumulatedTime >= time) {
			return keyframeIndex;
		}
	}
	return 0;
}

float BoneAnimationSequence_timeForKeyframeIndex(void * selfPtr, unsigned int keyframeIndex) {
	BoneAnimationSequence * self = selfPtr;
	unsigned int keyframeIndex2;
	float accumulatedTime = 0.0f;
	
	keyframeIndex %= self->numberOfKeyframes;
	for (keyframeIndex2 = 0; keyframeIndex2 < keyframeIndex; keyframeIndex2++) {
		accumulatedTime += self->keyframes[keyframeIndex2].duration;
	}
	return accumulatedTime;
}
