#include "mesh_3ds.h"
#include "../driver/mesh.h"
#include "../compile.h"
#include <sys/stat.h>

namespace sleek
{
    namespace loader
    {
        long filelenght(int f) noexcept
        {
            struct stat buf;
            fstat(f, &buf);
            return buf.st_size;
        }
        std::shared_ptr<driver::MeshBuffer> meshloader_3ds::read(io::filesystem *fs, const std::string &file) const noexcept
        {
            #ifdef mesh_loader_3ds_support
            unsigned char lchar = 0;
            unsigned int lchunk_lenght = 0;
            unsigned short lchunk_id = 0, lqty = 0, lface_flags = 0;

            //! original use 'rb'
            auto in = fs->read(file);

            if(!in){ printf("error: couldn't open \"%s\"!\n", file.c_str()); return 0; }
            printf("Load mesh: \"%s\"\n", file.c_str());

            auto tmp = std::make_shared<driver::MeshBuffer>();
            while(in->pos() < 200)
            {
                in->read(&lchunk_id, 2);
                in->read(&lchunk_lenght, 4);

                switch (lchunk_id)
                {
                    case 0x4d4d: break;
                    case 0x3d3d: break;
                    case 0x4000: break;
                    case 0x4100: break;
                    case 0x4110:
                        in->read(&lqty, sizeof(unsigned short));
                        tmp->vertices.resize(lqty);

                        for(u32 i = 0; i < lqty; i++)
                        {
                            in->read(&tmp->vertices[i].Pos.x, sizeof(f32));
                            in->read(&tmp->vertices[i].Pos.y, sizeof(f32));
                            in->read(&tmp->vertices[i].Pos.z, sizeof(f32));
                        }
                    break;
                    case 0x4120:
                        in->read(&lqty, sizeof(unsigned short));
                        tmp->indices.resize(lqty);

                        for(u32 i = 0; i < lqty; i++)
                        {
                            in->read(&tmp->indices[i].vertex[0], sizeof(unsigned short));
                            in->read(&tmp->indices[i].vertex[1], sizeof(unsigned short));
                            in->read(&tmp->indices[i].vertex[2], sizeof(unsigned short));
                            in->read(&lface_flags, sizeof(unsigned short));
                        }
                    break;
                    case 0x4140:
                        in->read(&lqty, sizeof(unsigned short));
                        for(u32 i = 0; i < lqty; i++)
                        {
                            in->read(&tmp->vertices[i].Coord.x, sizeof(f32));
                            in->read(&tmp->vertices[i].Coord.y, sizeof(f32));
                        }
                    break;
                    default:
                        in->seek(lchunk_lenght - 6, true);
                    break;
                }
            }
            return tmp;
            #else
                return nullptr;
            #endif
        }

        bool meshloader_3ds::write(io::filesystem *fs, driver::MeshBuffer*,const std::string&) const noexcept
        {
            return false;
        }

        bool meshloader_3ds::match(const std::string &filename) const noexcept
        {
            return filename.substr(filename.find_last_of('.')+1, 3) == "3ds";
        }
    }
}