#pragma once

#include <stdint.h>
#include <stdbool.h>
#include <math.h>
#include "pt2_header.h"

// fast 32-bit -> 16-bit clamp
#define CLAMP16(i) if ((int16_t)(i) != i) i = 0x7FFF ^ (i >> 31)

// fast 16-bit -> 8-bit clamp
#define CLAMP8(i) if ((int8_t)(i) != i) i = 0x7F ^ (i >> 15)

#define ALIGN_PTR(p, x) (((uintptr_t)(p) + ((x)-1)) & ~((x)-1))
#define MALLOC_PAD(size, pad) (malloc((size) + (pad)))

#define SWAP16(value) \
( \
	(((uint16_t)((value) & 0x00FF)) << 8) | \
	(((uint16_t)((value) & 0xFF00)) >> 8)   \
)

#define SWAP32(value) \
( \
	(((uint32_t)((value) & 0x000000FF)) << 24) | \
	(((uint32_t)((value) & 0x0000FF00)) <<  8) | \
	(((uint32_t)((value) & 0x00FF0000)) >>  8) | \
	(((uint32_t)((value) & 0xFF000000)) >> 24)   \
)

#define SGN(x) (((x) >= 0) ? 1 : -1)
#define ABS(a) (((a) < 0) ? -(a) : (a))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
#define LERP(x, y, z) ((x) + ((y) - (x)) * (z))

#define R12(x) (((x) >> 8) & 0xF)
#define G12(x) (((x) >> 4) & 0xF)
#define B12(x) ((x) & 0xF)

// 0..15 -> 0..255
#define R12_to_R24(x) (R12(x) * 17)
#define G12_to_G24(x) (G12(x) * 17)
#define B12_to_B24(x) (B12(x) * 17)

#define RGB12_to_RGB24(x) ((R12_to_R24(x) << 16) | (G12_to_G24(x) << 8) | (B12_to_B24(x)))

#define R24(x) (((x) >> 16) & 0xFF)
#define G24(x) (((x) >> 8) & 0xFF)
#define B24(x) ((x) & 0xFF)

#define RGB24(r, g, b) (((r) << 16) | ((g) << 8) | (b))

void showErrorMsgBox(const char *fmt, ...);

#ifdef _WIN32
// Windows usleep() implementation
void usleep(uint32_t usec);
void setupWin32Usleep(void);
void freeWin32Usleep(void);
#endif

void sanitizeFilenameChar(char *chr);
bool sampleNameIsEmpty(char *name);
bool moduleNameIsEmpty(char *name);
void updateWindowTitle(bool modified);
void recalcChordLength(void);
