#include <stdio.h>
#include <malloc.h>
#include <GL/glu.h>
#include "dms/FileImage.h"
#include "dms/Texture1D.h"

namespace dms
{

Texture1D::Texture1D(char *filename, GLint wrap, GLint min, GLint mag) :
                Texture(wrap,min,mag)
    {
    id_ = 0;
    image_ = 0;
    rescaledImageData_ = 0;
    defined_ = false;
    createdImage_ = false;
    if (filename)
        {
        image_ = new FileImage(filename);
        createdImage_ = true;
        }
    }


Texture1D::Texture1D(Image& image, GLint wrap, GLint min, GLint mag) :
                Texture(wrap,min,mag)
    {
    id_ = 0;
    rescaledImageData_ = 0;
    defined_ = false;
    createdImage_ = false;
    setImage(image);
    }


Texture1D::~Texture1D(void)
    {
    if (rescaledImageData_)
        ::free(rescaledImageData_);
    if (createdImage_)
        delete image_;
    }


void Texture1D::define(void)
    {
    GLsizei xdim2;
    void *imgp;
    defined_ = true;
    if ((!image_) || (!image_->data()))
        return;
    xdim2 = 1;
    while (xdim2 <= image_->width())
        xdim2 *= 2;
    xdim2 /= 2;
    if (image_->width() != xdim2)
        {
        rescaledImageData_ = (unsigned long *) ::malloc(xdim2 *
                            sizeof(unsigned long));
        gluScaleImage(GL_RGBA, image_->width(), 1,
                      GL_UNSIGNED_BYTE, image_->data(), xdim2, 1,
                      GL_UNSIGNED_BYTE, rescaledImageData_);
        imgp = rescaledImageData_;
        }
    else
        imgp = image_->data();
    if (id_ == 0)
        glGenTextures(1, &id_);
    glBindTexture(GL_TEXTURE_1D, id_);
    if ((minFilter() == GL_NEAREST_MIPMAP_NEAREST) ||
          (minFilter() == GL_NEAREST_MIPMAP_LINEAR) ||
          (minFilter() == GL_LINEAR_MIPMAP_NEAREST) ||
          (minFilter() == GL_LINEAR_MIPMAP_LINEAR))
        gluBuild1DMipmaps(GL_TEXTURE_1D, GL_RGBA, xdim2, GL_RGBA,
                          GL_UNSIGNED_BYTE, imgp);
    else
        glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, xdim2, 0, GL_RGBA,
                     GL_UNSIGNED_BYTE, imgp);
    glTexParameterf(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,magFilter());
    glTexParameterf(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,minFilter());
    glTexParameterf(GL_TEXTURE_1D,GL_TEXTURE_WRAP_S,wrapS());
    glBindTexture(GL_TEXTURE_1D,0);
    }


void Texture1D::apply(void)
    {
    if (!defined_)
        define();
    if (id_)
        {
        glBindTexture(GL_TEXTURE_1D,id_);
        glEnable(GL_TEXTURE_1D);
        }
    else
        {
        glBindTexture(GL_TEXTURE_1D,0);
        glDisable(GL_TEXTURE_1D);
        }
    }


void Texture1D::disable(void)
    {
    glBindTexture(GL_TEXTURE_1D,0);
    glDisable(GL_TEXTURE_1D);
    }


void Texture1D::setImage(Image& im)
    {
    image_ = &im;
    }

}
