#include <iostream>
#include <vector>
#include <chrono>
#include <sys/shm.h>
#include <cstring>
#include "shm_keys.hpp"
#include "row.hpp"
#include "sort_algorithms.hpp"

// Context για τους πίνακες
struct MatrixSortContext {
    uint8_t* A;
    int F, H, W;
};

// Δηλώσεις των Schedulers (πρέπει να προσαρμοστούν στα .cpp τους)
extern long long run_static(MatrixSortContext* ctx, int K);
extern long long run_dynamic(MatrixSortContext* ctx, int K);
extern long long run_guided(MatrixSortContext* ctx, int K);
extern long long run_adaptive(MatrixSortContext* ctx, int K);
extern long long run_aimd(MatrixSortContext* ctx, int K);
extern long long run_chunk(MatrixSortContext* ctx, int K);
extern long long run_steal(MatrixSortContext* ctx, int K);

int main(int argc, char** argv) {
    if (argc < 5) {
        std::cout << "Usage: ./shm_benchmark F H W K\n";
        return 1;
    }

    int F = atoi(argv[1]);
    int H = atoi(argv[2]);
    int W = atoi(argv[3]);
    int K = atoi(argv[4]);
    size_t totalBytes = (size_t)F * H * W;

    // Σύνδεση στην Original SHM
    int orig_id = shmget(SHM_KEY_ORIGINAL, totalBytes, 0666);
    uint8_t* original = (uint8_t*)shmat(orig_id, nullptr, 0);

    // Λίστα με Keys και Ονόματα για το Loop
    std::vector<std::pair<int, std::string>> schedulers = {
        {SHM_KEY_STATIC, "Static"}, {SHM_KEY_DYNAMIC, "Dynamic"},
        {SHM_KEY_GUIDED, "Guided"}, {SHM_KEY_ADAPTIVE, "Adaptive"},
        {SHM_KEY_AIMD, "AIMD"},     {SHM_KEY_CHUNK, "Chunk"},
        {SHM_KEY_STEAL, "Steal"}
    };

    for (auto& s : schedulers) {
        int shmid = shmget(s.first, totalBytes, IPC_CREAT | 0666);
        uint8_t* addr = (uint8_t*)shmat(shmid, nullptr, 0);
        memcpy(addr, original, totalBytes); // Φρεσκάρισμα δεδομένων

        MatrixSortContext ctx = {addr, F, H, W};
        long long ms = 0;

        // Κλήση ανάλογα με το όνομα (απλοποιημένο παράδειγμα)
        if (s.second == "Static") ms = run_static(&ctx, K);
        else if (s.second == "Dynamic") ms = run_dynamic(&ctx, K);
        else if (s.second == "Guided") ms = run_guided(&ctx, K);
        else if (s.second == "Adaptive") ms = run_adaptive(&ctx, K);
        else if (s.second == "AIMD") ms = run_aimd(&ctx, K);
        else if (s.second == "Chunk") ms = run_chunk(&ctx, K);
        else if (s.second == "Steal") ms = run_steal(&ctx, K);

        std::cout << s.second << " Scheduler Time: " << ms << " ms\n";
        shmdt(addr);
    }

    shmdt(original);
    return 0;
}