/*********************************************************************
*                                                                    *          
*                              FLY                                   *
*                           --E#Y#E--				     *
*                         ===MUSCLE===                               *
*                                                                    *
*********************************************************************/
/* Header Files */
#include "targa.h"

#include <cstdio>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>

//---------------------------------------------------------------------------

namespace tga {

TARGA::TARGA(FILE* file)
        : m_file(file)
        , m_ok(true)
{
}

bool TARGA::ok() const
{
        return m_ok;
}

size_t TARGA::tell()
{
        return ftell(m_file);
}

void TARGA::seek(size_t absPos)
{
        // To detect surprises with the size_t -> long cast.
        assert(absPos <= std::numeric_limits<long>::max());

        fseek(m_file, (long)absPos, SEEK_SET);
}

uint8_t TARGA::read8()
{
        int value = fgetc(m_file);
        if (value != EOF) {
        // We can safely cast to uint8_t as EOF is the only special
        // non-uint8 value than fgetc() should return.
        return (uint8_t)value;
        }

        m_ok = false;
        return 0;
}

void TARGA::write8(uint8_t value)
{
        fputc(value, m_file);
}

} // namespace tga

//---------------------------------------------------------------------------

/*
class MEM : public tga::FileInterface {

MEM(const uint8_t* data, size_t size)
        : m_data(data)
        , m_size(size)
        , m_pos(0)
        , m_ok(true) 
{
}
  
bool ok() const override
{
        return m_ok;
}
  
size_t tell() override
{ 
        return m_pos; 
}
  
void seek(size_t absPos) override
{
        if (absPos >= m_size) 
        {
              m_pos = m_size;
              m_ok = false;
        }
        else 
        {
              m_pos = absPos;
              m_ok = true;
        }
}
  
uint8_t read8() override
{
        if (!m_ok) return 0;
        if (m_pos >= m_size) 
        {
              m_ok = false;
              return 0;
        }
        return m_data[m_pos++];
}
  
void write8(uint8_t value) override
{
        // unused
        assert(false);
}

private:
const uint8_t* m_data;
size_t m_size;
size_t m_pos;
bool m_ok; 

}; // namespace tga
*/
 
//---------------------------------------------------------------------------

/* Load Targa */
int TARGA::readTarga(const char *name, unsigned char **Data)
{
	/* Load File */
	FILE *texture;
	texture=std::fopen(name,"rb");
        tga::TARGA file(texture);        
        //MEM file(name, test);
        
        /* Decoder */
        tga::Decoder decoder(&file);
        tga::Header header;
        
        /* Read Header */
        if(!decoder.readHeader(header))
        {
                return 1;
        }

        /* Targa Image */
        tga::Image image;
        image.bytesPerPixel = header.bytesPerPixel();
        image.rowstride = header.width * header.bytesPerPixel();
        
        if(image.rowstride * header.height > 1024*1024*1024) // No more than 1 GB
        {        
                return 0;
        }
        
        /* Image Buffer */
        std::vector<uint8_t> buffer(image.rowstride * header.height);
        image.pixels = &buffer[0];
        //*Data = &buffer[0];

        /* Read Image */
        if(!decoder.readImage(header, image, nullptr))
        {
                return 2;
        }
        
        // Optional post-process to fix the alpha channel in
        // some TGA files where alpha=0 for all pixels when
        // it shouldn't.
        decoder.postProcessImage(header, image);
        
        /* File Close */
	fclose(texture);
	
	return 0;
}

//---------------------------------------------------------------------------


