#ifndef _UTILS_H_
#define _UTILS_H_

#include <cuda_runtime.h>
#define _USE_MATH_DEFINES
#include <math.h>

uchar4* load_image_opencv(const char* filename, int* iw, int* ih);
void fps_tracker_update(float current_fps, int active_count);
void kernel_timer_record(cudaEvent_t start, cudaEvent_t stop);
void kernel_timer_print();
void draw_bin_grid(int window_width, int window_height, int bin_dim_x,
                   int bin_dim_y);

void print_kernel_occupancy(const char* name, const void* kernel,
                            size_t shared_mem, int block_size);

typedef struct
{
	uint8_t type;
	uint8_t tracked;
	uint8_t active;

	float rotation;
	float gravity;

	float lifetime;
	float max_lifetime;

	float amplitude;
	float frequency;
	float phase;
	float wave_phase;
	float2 origin;

	float2 pos;
	float2 old_pos;
	float2 velocity;


} Projectile;

/* I don't trust the compiler to not inline this, so we force it. */
__host__ __device__ __forceinline__ void
update_standard_projectile_velocity(Projectile* p, float grav_x, float grav_y,
                                    float delta_t, float normalized_dt)
{
	p->velocity.x += grav_x * normalized_dt;
	p->velocity.y += grav_y * normalized_dt;

	float speed =
		sqrtf(p->velocity.x * p->velocity.x + p->velocity.y * p->velocity.y);

	p->old_pos = p->pos;
	p->pos.x += p->velocity.x * delta_t;
	p->pos.y += p->velocity.y * delta_t;

	if (p->amplitude != 0.0f && speed > 0.0f)
	{
		float px = -p->velocity.y / speed;
		float py = p->velocity.x / speed;
		float wave = p->amplitude * sinf(p->lifetime * p->frequency + p->phase);
		p->pos.x += px * wave * normalized_dt;
		p->pos.y += py * wave * normalized_dt;
	}

	p->lifetime += normalized_dt;

	float dx = p->pos.x - p->old_pos.x;
	float dy = p->pos.y - p->old_pos.y;
	p->rotation = atan2f(dy, dx) * (180.0f / (float)M_PI);

	if (p->lifetime > p->max_lifetime)
	{
		p->active = 0;
	}
}


#endif