module tests.access_perf;

import tests.runner;

import bubel.ecs.core;
import bubel.ecs.manager;
import bubel.ecs.entity;

import std.array : staticArray;

import core.stdc.stdio;

struct CLong
{
    mixin ECS.Component;

    alias value this;

    long value = 10;
}

struct CInt
{
    mixin ECS.Component;

    alias value this;

    int value = 10;
}

struct CUInt
{
    mixin ECS.Component;

    alias value this;

    uint value = 12;
}

struct CBig
{
    mixin ECS.Component;
    uint[32] data;
}

EntityTemplate* tmpl;

void beforeEveryTest()
{
    gEM.initialize(0);

    gEM.beginRegister();

    gEM.registerComponent!CLong;
    gEM.registerComponent!CInt;
    gEM.registerComponent!CUInt;
    gEM.registerComponent!CBig;

    gEM.endRegister();

    tmpl = gEM.allocateTemplate([CLong.component_id, CInt.component_id, CUInt.component_id, CBig.component_id].staticArray);
    foreach(i; 0 .. 100_000)gEM.addEntity(tmpl);
}

void afterEveryTest()
{
    if(tmpl)gEM.freeTemplate(tmpl);
    tmpl = null;
    gEM.destroy();
}

@("DirectAccess100k1comp") 
unittest
{
    foreach(i;0..25000)
    {
        Entity* entity = gEM.getEntity(EntityID(i*4+1,0));
        CUInt* comp1 = entity.getComponent!CUInt;
        comp1.value = 4;
    }
}

@("DirectAccess100k4comp") 
unittest
{
    foreach(i;0..25000)
    {
        Entity* entity = gEM.getEntity(EntityID(i*4+1,0));
        CUInt* comp1 = entity.getComponent!CUInt;
        comp1.value = 4;
        CInt* comp2 = entity.getComponent!CInt;
        comp2.value = 3;
        CLong* comp3 = entity.getComponent!CLong;
        comp3.value = 1;
        CBig* comp4 = entity.getComponent!CBig;
        comp4.data[0] = 2;
    }
}

@("DirectAccess100k1compWithMeta") 
unittest
{
    foreach(i;0..25000)
    {
        Entity* entity = gEM.getEntity(EntityID(i*4+1,0));
        EntityMeta meta = entity.getMeta();
        CUInt* comp1 = meta.getComponent!CUInt;
        comp1.value = 4;
    }
}

@("DirectAccess100k4compWithMeta") 
unittest
{
    foreach(i;0..25000)
    {
        Entity* entity = gEM.getEntity(EntityID(i*4+1,0));
        EntityMeta meta = entity.getMeta();
        CUInt* comp1 = meta.getComponent!CUInt;
        comp1.value = 4;
        CInt* comp2 = meta.getComponent!CInt;
        comp2.value = 3;
        CLong* comp3 = meta.getComponent!CLong;
        comp3.value = 1;
        CBig* comp4 = meta.getComponent!CBig;
        comp4.data[0] = 2;
    }
}