#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <sys/mman.h>

#include "schedulers.h"

using namespace std;

//Helper for cleaning indexing
//(Access helper for continuous shared video buffer) where uint& PIXEL

int& CELL(int *B, int s, int i, int j, int n)
{
	return B[s*n*n + i*n +j];
}

int* createSharedTensor(size_t totalBytes)
{
	int *ptr = (int*) mmap(
		nullptr,
		totalBytes,
		PROT_READ | PROT_WRITE,
		MAP_SHARED | MAP_ANONYMOUS,
		-1,
		0
	);

	if(ptr == MAP_FAILED) {
		perror("mmap failed");
		exit(1);
	}

	return ptr;

}

void printTensor(int *B, int n, int k, const string& title)
{
	cout << "\n" << title << "\n";
	for(int s = 0; s<k; s++){
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				cout<< CELL(B, s, i, j, n) << " ";
			}
			cout << "\n";
		}
		cout << "\n";
	}
}






int main()
{
	int n, k;

	cout << "Give n: ";
	cin >> n;

	cout << "Give k: ";
	cin >> k;

	srand(time(0));


	size_t totalBytes = n*n*k* sizeof(int);

	int *B_original = createSharedTensor(totalBytes);

/*	(int*) mmap(
		nullptr,
		totalBytes,
		PROT_READ | PROT_WRITE,
		MAP_SHARED | MAP_ANONYMOUS,
		-1,
		0
	);

	if(B == MAP_FAILED) {
		perror("mmap failed");
		return -1;
	}
*/



	//fill tensor
	for(int s=0; s<k; s++){
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				CELL(B_original, s, i, j, n) = rand() % 2001 - 1000;
			}
		}
	}





	//CREATE THE DUPES

	int *B_prolific = createSharedTensor(totalBytes);
	int *B_collective = createSharedTensor(totalBytes);

	memcpy(B_prolific, B_original, totalBytes);
	memcpy(B_collective, B_original, totalBytes);



	//print original

	printTensor(B_original, n, k, "Original Tensor B");

	//run prolific

	ProlificScheduler prolific;
	prolific.run(B_prolific, n, k);

	//run collective

	CollectiveScheduler collective;
	collective.run(B_collective, n, k);

	//print after rorting
	printTensor(B_prolific, n, k, "Tensor after being sorted by the prolific scheduler");
	printTensor(B_collective, n, k, "Tensor after being sorted by the collective scheduler");
	



	//free shared mmry
	munmap(B_original, totalBytes);
	munmap(B_prolific, totalBytes);
	munmap(B_collective, totalBytes);

	return 0;
}
