
#include "Utils.hpp"

#include <ctime>
#include <random>

void initializeCallStackCapture();
void deinitializeCallStackCapture();

static bool initialize(const tp::ModuleManifest*) {
	initializeCallStackCapture();
	// std::srand(std::time(nullptr));
	return true;
}

static void deinitialize(const tp::ModuleManifest*) {
	deinitializeCallStackCapture();
}

namespace tp {

	void memSetVal(void* p, uhalni byteSize, uint1 val) {
		alni alignedVal = val;
		alignedVal = (alignedVal << 8) | alignedVal;
		alignedVal = (alignedVal << 16) | alignedVal;
		alignedVal = (alignedVal << 32) | alignedVal;

		ualni alignedLen = byteSize / sizeof(alni);
		for (ualni idx = 0; idx < alignedLen; idx++) {
			((alni*) p)[idx] = alignedVal;
		}

		ualni unalignedLen = byteSize - (alignedLen * sizeof(alni));
		for (ualni idx = 0; idx < unalignedLen; idx++) {
			((uint1*) p)[byteSize - idx - 1] = val;
		}
	}

	void memCopy(void* left, const void* right, uhalni len) {
		ualni alignedLen = len / sizeof(alni);
		for (ualni idx = 0; idx < alignedLen; idx++) {
			((alni*) left)[idx] = ((alni*) right)[idx];
		}

		ualni unalignedLen = len - (alignedLen * sizeof(alni));
		for (ualni idx = 0; idx < unalignedLen; idx++) {
			((uint1*) left)[len - idx - 1] = ((uint1*) right)[len - idx - 1];
		}
	}

	int1 memCompare(const void* left, const void* right, uhalni len) {
		if (!len) return 0;

		ualni alignedLength = len / sizeof(alni);
		for (ualni idx = 0; idx < alignedLength; idx++) {
			if (((alni*) left)[idx] == ((alni*) right)[idx]) {
				continue;
			}
			if (((alni*) left)[idx] > ((alni*) right)[idx]) {
				return 1;
			}
			return -1;
		}

		ualni unalignedLength = len - (alignedLength * sizeof(alni));
		for (ualni idx = 0; idx < unalignedLength; idx++) {
			if (((uint1*) left)[len - idx - 1] == ((uint1*) right)[len - idx - 1]) {
				continue;
			}
			if (((uint1*) left)[len - idx - 1] > ((uint1*) right)[len - idx - 1]) {
				return 1;
			}
			return -1;
		}
		return 0;
	}

	bool memEqual(const void* left, const void* right, uhalni len) { return memCompare(left, right, len) == 0; }

	int1 memCompareVal(const void* left, uhalni len, uint1 val) {
		if (!len) return 0;

		alni valAligned = val;
		valAligned = (valAligned << 8) | valAligned;
		valAligned = (valAligned << 16) | valAligned;
		valAligned = (valAligned << 32) | valAligned;

		ualni alignedLength = len / sizeof(alni);
		for (ualni idx = 0; idx < alignedLength; idx++) {
			if (((alni*) left)[idx] == valAligned) {
				continue;
			}
			if (((alni*) left)[idx] > valAligned) {
				return 1;
			}
			return -1;
		}

		ualni unalignedLength = len - (alignedLength * sizeof(alni));
		for (ualni idx = 0; idx < unalignedLength; idx++) {
			if (((uint1*) left)[len - idx - 1] == val) {
				continue;
			}
			if (((uint1*) left)[len - idx - 1] > val) {
				return 1;
			}
			return -1;
		}
		return 0;
	}

	alnf randomFloat() {
		alnf r = static_cast<alnf>(std::rand()) / static_cast<alnf>(RAND_MAX);
		return r;
	}
}