module demos.simple;

import app;

import bindbc.sdl;

import cimgui.cimgui;

import ecs.attributes;
import ecs.core;
import ecs.entity;
import ecs.manager;
import ecs.std;

import ecs_utils.gfx.texture;
import ecs_utils.math.vector;
import ecs_utils.utils;

extern(C):

struct Simple
{
    __gshared const (char)* tips = "Use \"space\" to spwan entities.\n\nSystems can be enabled/disabled from \"Simple\" window.";

    EntityTemplate* tmpl;
    Texture texture;

    bool move_system = true;
    bool draw_system = true;
}

struct CLocation
{
    mixin ECS.Component;

    alias location this;

    vec2 location;
}

struct CTexture
{
    mixin ECS.Component;

    Texture tex;
}

struct DrawSystem
{
    mixin ECS.System!1;

    struct EntitiesData
    {
        uint length;
        @readonly CTexture[] textures;
        @readonly CLocation[] locations;
    }

    void onUpdate(EntitiesData data)
    {
        foreach(i; 0..data.length)
        {
            launcher.renderer.draw(data.textures[i].tex, data.locations[i].location, vec2(32,32), vec4(0,0,1,1), 0, 0 , 0);
            //draw(renderer, data.textures[i].tex, data.locations[i], vec2(32,32), vec4(0,0,1,1));
        }
    }
}

struct MoveSystem
{
    mixin ECS.System!64;

    struct EntitiesData
    {
        uint length;
        CLocation[] locations;
    }

    void onUpdate(EntitiesData data)
    {
        foreach(i; 0..data.length)
        {
            data.locations[i].location.y = data.locations[i].location.y + 1; 
            if(data.locations[i].location.y > 400)data.locations[i].location.y = 0;
        }
    }
}

__gshared Simple* simple;

void simpleStart()
{
    simple = Mallocator.make!Simple;

    simple.texture.create();
    simple.texture.load("assets/textures/buckler.png");

    launcher.manager.beginRegister();

    launcher.manager.registerComponent!CLocation;
    launcher.manager.registerComponent!CTexture;

    launcher.manager.registerSystem!MoveSystem(0);
    launcher.manager.registerSystem!DrawSystem(1);

    launcher.manager.endRegister();

    launcher.gui_manager.addSystem(MoveSystem.system_id,"Move System");
    launcher.gui_manager.addSystem(DrawSystem.system_id,"Draw System");

    ushort[2] components = [CLocation.component_id, CTexture.component_id];
    simple.tmpl = launcher.manager.allocateTemplate(components);
    CTexture* tex_comp = simple.tmpl.getComponent!CTexture;
    tex_comp.tex = simple.texture;
    CLocation* loc_comp = simple.tmpl.getComponent!CLocation;

    launcher.gui_manager.addTemplate(simple.tmpl, "Basic");

    foreach(i; 0..10)
        foreach(j; 0..10)
        {
            loc_comp.location = vec2(i*32+64,j*32+64);
            launcher.manager.addEntity(simple.tmpl);
        }
}

void simpleEnd()
{
    launcher.manager.getSystem(MoveSystem.system_id).disable();
    launcher.manager.getSystem(DrawSystem.system_id).disable();

    simple.texture.destroy();

    //launcher.manager.freeTemplate(simple.tmpl);
    Mallocator.dispose(simple);
}

void simpleTool(vec2 position, Tool tool, int size)
{
    switch(tool)
    {
        case Tool.entity_spawner:
            {
                EntityTemplate* tmpl = launcher.gui_manager.getSelectedTemplate();
                CLocation* location = tmpl.getComponent!CLocation;
                if(location)
                {
                    position.x += (randomf - 0.5) * size;
                    position.y += (randomf - 0.5) * size;
                    *location = position;
                }
                launcher.manager.addEntity(tmpl);
            }
            break;
        default:
            break;
    }
}

void simpleEvent(SDL_Event* event)
{
    /*if(event.type == event.button)
    {
        vec2 position = vec2(event.button.x, event.button.y);
        
    }*/
}

void spawnEntity()
{
    CLocation* loc_comp = simple.tmpl.getComponent!CLocation;
    loc_comp.location = vec2(randomf() * 600,0);
    launcher.manager.addEntity(simple.tmpl);
}

bool simpleLoop()
{
    if(launcher.getKeyState(SDL_SCANCODE_SPACE))
    {
        foreach(i;0..1)spawnEntity();
    }

    
    launcher.manager.begin();
    if(launcher.multithreading)
    {
        launcher.job_updater.begin();
        launcher.manager.updateMT();
        launcher.job_updater.call();
    }
    else
    {
        launcher.manager.update();
    }
    launcher.manager.end();

    return true;
}