module ecs_utils.gfx.mesh;

import bindbc.sdl;

import ecs.std;

import ecs_utils.gfx.buffer;

import glad.gl.gl;
//import mutils.serializer.json;

extern(C):

struct Mesh
{
    bool load(const char[] path) nothrow
    {
        struct LoadData
        {
            /*struct Vertex
            {
                struct Binding
                {
                    @("malloc") string type;
                    uint stride;
                }
                @("malloc") Binding[] bindings;
            }
            Vertex vertex;*/
            @("malloc") ushort[] indices;
            @("malloc") float[] vertices;
            //int i;

            void dispose() nothrow
            {
                if(indices)Mallocator.dispose(indices);
                if(vertices)Mallocator.dispose(vertices);

                /*foreach(binding; vertex.bindings)Mallocator.instance.dispose(cast(char[])binding.type);

                if(vertex.bindings)Mallocator.instance.dispose(vertex.bindings);*/
            }
        }

        char[] cpath = (cast(char*)alloca(path.length+1))[0..path.length+1];
        cpath[0..$-1] = path[0..$];
        cpath[$-1] = 0;

        SDL_RWops* file = SDL_RWFromFile(cpath.ptr,"r");//SDL_LoadFile(cpath.ptr,);
        if(file)
        {
            size_t size = cast(size_t)SDL_RWsize(file);
            //data.code = Mallocator.instance.makeArray!char(size);
            //data.code[$-1] = 0;
            char[] buffer = Mallocator.makeArray!char(size);
            SDL_RWread(file,buffer.ptr,size,1);

            LoadData load_data;
            scope(exit)load_data.dispose();

            /*JSONSerializer serializer = Mallocator.make!JSONSerializer;
            scope(exit)Mallocator.dispose(serializer);
            serializer.serialize!(Load.yes, true)(load_data,buffer);*/

            indices = Mallocator.makeArray(load_data.indices);
            /*vertex.create();
            Vertex.Binding[] bindings = (cast(Vertex.Binding*)alloca(Vertex.Binding.sizeof*load_data.vertex.bindings.length))[0..load_data.vertex.bindings.length];
            uint vertex_size = 0;
            uint alignment = 4;
            foreach(i, binding;load_data.vertex.bindings)
            {
                uint new_size = binding.stride;
                bindings[i].stride = binding.stride;
                if(binding.type == "float_rg")
                {
                    bindings[i].type = Vertex.Type.float_rg;
                    new_size += 8;
                }
                if(new_size > vertex_size)vertex_size = new_size;
                //new_size = new_size + (3 - (new_size)%alignment)
            }
            vertex.data.size = vertex_size;
            vertex.attachBindings(bindings);*/

            vertices = Mallocator.makeArray(load_data.vertices);
            /*vertices = Mallocator.instance.makeArray!ubyte(vertex_size * load_data.vertices.length);
            {
                foreach()
            }*/

            SDL_RWclose(file);
            load_data.dispose();
            return true;
        }
        else return false;
    }

    void uploadData() nothrow
    {
        vbo.create();
        vbo.bufferData(Buffer.BindTarget.array,16,cast(uint)vertices.length,GL_STATIC_DRAW,vertices.ptr);

        ibo.create();
        ibo.bufferData(Buffer.BindTarget.element_array,2,cast(uint)indices.length,GL_STATIC_DRAW,indices.ptr);
    }

    void bind() nothrow
    {
        vbo.bind(Buffer.BindTarget.array);
        ibo.bind(Buffer.BindTarget.element_array);

        glVertexAttribPointer(0,2,GL_FLOAT,false,16,null);
        glVertexAttribPointer(1,2,GL_FLOAT,false,16,cast(void*)8);
    }

    float[] vertices;
    ushort[] indices;
    Buffer vbo;
    Buffer ibo;
    //Vertex vertex;
}