#ifndef __TIMING____H__
#define __TIMING____H__

#include "Constants.h"
#include <SDL.h>

#define TIMING_LEFT_BORDER_TSTATES 24
#define TIMING_PAPER_TSTATES 128
#define TIMING_RIGHT_BORDER_TSTATES 24
#define TIMING_HORIZONTAL_RETRACE_BORDER_TSTATES 48
#define TIMING_SCANLINE_TSTATES (TIMING_LEFT_BORDER_TSTATES + TIMING_PAPER_TSTATES + TIMING_RIGHT_BORDER_TSTATES + TIMING_HORIZONTAL_RETRACE_BORDER_TSTATES)

Uint32 timing_get_states_per_scanline_allocation();
void timing_report_actual_states_last_scanline(Uint32 actualTstates);

Uint64 timing_get_states_per_video_frame();
Uint16 timing_get_target_milliseconds_per_video_frame();

// actual, as averaged over the entire run time
double timing_get_actual_milliseconds_per_video_frame();
void timing_set_actual_milliseconds_per_video_frame(double actualMsPerVideoFrame);

// due to the low resolution of ftime(), it is unfeasible to record the frame time of
// individual frames, since their target run time is so close to the 18ms resolution of ftime
// thus, the approach is to record unusually slow frames as "idle time", and then subtracting
// that from timing calculations. this is because unusually slow frames can be more accurately
// timed via ftime, since they take much longer than the resolution of ftime
void timing_record_idle_time(Uint64 durationMs);
Uint64 timing_get_total_real_idle_time();
Uint64 timing_get_total_real_idle_time_spent_while_faster();

Uint8 timing_is_faster();
Uint64 timing_get_total_real_time_spent_while_faster();

void timing_apply_tstate_factor(Uint8 factor);

void timing_start(Uint16 millisecondsPerVideoFrame);
void timing_prepare_destroy();
void timing_destroy();

#endif  // !__TIMING____H__
