#ifndef _TMABITMAP_CPP_
#define _TMABITMAP_CPP_

#include <math.h>
#include "ma_allegro.h"

REGISTER_CLASS_ID(TMABitmap);

PMAGame TMABitmap::GMAGame = NULL;

TMABitmap::TMABitmap(BITMAP *bmp,bool shared)
{
    io_bmp = bmp;
    ib_destroy = (!shared);
}

PMABitmap TMABitmap::create(int width,int height,bool videomem)
{
    PMABitmap lbitmap=NULL;
    BITMAP *bmp = (videomem)?create_video_bitmap(width,height):create_bitmap(width,height);
    if (!bmp) return NULL;
    
    lbitmap = new TMABitmap(bmp);
    if (!lbitmap)
    {
        destroy_bitmap(bmp);
        return NULL;
    }        
    return lbitmap;            
}
        
PMABitmap TMABitmap::create(int width,int height,int depth)
{
    PMABitmap lbitmap=NULL;
    BITMAP *bmp = create_bitmap_ex(depth,width,height);
    if (!bmp) return NULL;
       
    lbitmap = new TMABitmap(bmp);
    if (!lbitmap)
    {
        destroy_bitmap(bmp);
        return NULL;
    }        
    return lbitmap;            
}

PMABitmap TMABitmap::loadFromFile(const char *filename)
{
    BITMAP* bmp;
    PALETTE rgb;
    
    bmp = load_bitmap(filename,rgb);

    if (!bmp) return NULL;
    
    PMABitmap lbmp = new TMABitmap(bmp);
    return lbmp;
}

bool TMABitmap::saveToFile(const char *filename)
{
    PALETTE rgb;
    
    get_palette(rgb);
    return (save_png(filename,io_bmp,rgb)==0);
}

TMABitmap::~TMABitmap()
{
    if (ib_destroy && (io_bmp!=NULL))
    {
        destroy_bitmap(io_bmp);
    }
}       

int TMABitmap::getColorDepth(void)
{
    return bitmap_color_depth(io_bmp);
}

int TMABitmap::getWidth(void)
{
    return io_bmp->w;
}

int TMABitmap::getHeight(void) 
{
    return io_bmp->h;
}

void TMABitmap::getSize(int& width,int& height)
{
    width = io_bmp->w;
    height = io_bmp->h;
}

void TMABitmap::draw(const PMABitmap origen,int px,int py,bool transparent)
{
    int w,h;
    origen->getSize(w,h);
    draw(origen,0,0,w,h,px,py,transparent);
}

void TMABitmap::draw(const PMABitmap origen,int ox,int oy,int width,int height,
                     int dx,int dy,bool transparent)
{
    if (transparent) masked_blit(origen->io_bmp,io_bmp,ox,oy,dx,dy,width,height);
    else blit(origen->io_bmp,io_bmp,ox,oy,dx,dy,width,height);
}

void TMABitmap::drawSprite(const PMABitmap origen,int px,int py,bool flipx,bool flipy)
{
    if (flipx && flipy) draw_sprite_vh_flip(io_bmp,origen->io_bmp,px,py);
    else if (flipx) draw_sprite_h_flip(io_bmp,origen->io_bmp,px,py);
    else if (flipy) draw_sprite_v_flip(io_bmp,origen->io_bmp,px,py);
    else draw_sprite(io_bmp,origen->io_bmp,px,py);
}

void TMABitmap::drawSpriteAlpha(const PMABitmap spr,int px,int py,bool flipx,bool flipy,int alpha)
{
    PMABitmap bmp = TMABitmap::create(spr->io_bmp->w,spr->io_bmp->h,bitmap_color_depth(spr->io_bmp));
    bmp->clear(TMAGame::getRGBColor(255,0,255));
    bmp->drawSprite(spr,0,0,flipx,flipy);
    setAlpha(alpha);
    drawAlpha(bmp,px,py);
    delete bmp;
}

void TMABitmap::drawSpriteColorized(const PMABitmap spr,int px,int py,bool flipx,bool flipy,int r,int g,int b)
{
    PMABitmap bmp = TMABitmap::create(spr->io_bmp->w,spr->io_bmp->h,bitmap_color_depth(spr->io_bmp));
    bmp->clear(TMAGame::getRGBColor(255,0,255));
    bmp->drawSprite(spr,0,0,flipx,flipy);
    
    int trans = makecol(255,0,255);
    for (int x=0;x<bmp->io_bmp->w;x++)
    for (int y=0;y<bmp->io_bmp->h;y++)
    {
        int color_value = getpixel(bmp->io_bmp, x, y);
        if (color_value!=trans)
        {
            int r1 = getr(color_value)*r/255;
            int g1 = getg(color_value)*g/255;
            int b1 = getb(color_value)*b/255;
            putpixel(bmp->io_bmp,x,y,makecol(r1,g1,b1));
        }
    } 
    draw_sprite(io_bmp,bmp->io_bmp,px,py);       
    delete bmp;
}       

void TMABitmap::modifyAlphaChannel(void)
{
     set_write_alpha_blender();
     drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
}

void TMABitmap::endModifyAlphaChannel(void)
{
     solid_mode();
}
   
void TMABitmap::drawAlphaBlending(const PMABitmap spr,int px,int py)
{
    draw_trans_sprite(io_bmp,spr->io_bmp,px,py);
}

void TMABitmap::setAlphaBlending(void)
{
    set_alpha_blender();
}
    
void TMABitmap::setAlpha(int alpha)
{
    set_trans_blender(alpha,alpha,alpha,alpha);
}

void TMABitmap::drawAlpha(const PMABitmap origen,int px,int py)
{
    draw_trans_sprite(io_bmp,origen->io_bmp,px,py);
}


void TMABitmap::clear(int red,int green,int blue)
{
    clear_to_color(io_bmp,TMAGame::getRGBColor(red,green,blue));
}

void TMABitmap::clear(int color)
{
    clear_to_color(io_bmp,color);
}

int  TMABitmap::getPixel(int px,int py)
{
    return getpixel(io_bmp,px,py);
}

void TMABitmap::setPixel(int px,int py,int color)
{
    putpixel(io_bmp,px,py,color);
}

void TMABitmap::drawLine(int ox,int oy,int dx,int dy,int color)
{
    line(io_bmp,ox,oy,dx,dy,color);
}

void TMABitmap::drawRect(int ox,int oy,int dx,int dy,int color)
{
    rect(io_bmp,ox,oy,dx,dy,color);
}

void TMABitmap::drawRectFilled(int ox,int oy,int dx,int dy,int color)
{
    rectfill(io_bmp,ox,oy,dx,dy,color);
}

void TMABitmap::drawCircle(int cx,int cy,int radio,int color)
{
    circle(io_bmp,cx,cy,radio,color);
}

void TMABitmap::drawCircleFilled(int cx,int cy,int radio,int color)
{
    circlefill(io_bmp,cx,cy,radio,color);
}

void TMABitmap::drawEllipse(int cx,int cy,int radiox,int radioy,int color)
{
    ellipse(io_bmp,cx,cy,radiox,radioy,color);
}

void TMABitmap::drawEllipseFilled(int cx,int cy,int radiox,int radioy,int color)
{
    ellipsefill(io_bmp,cx,cy,radiox,radioy,color);
}

void TMABitmap::paint(int px,int py,int color)
{
    floodfill(io_bmp,px,py,color);
}

void TMABitmap::setTransparentColor(int color)
{
    int trans = TMAGame::getRGBColor(255,0,255);
    
    // Si el color que se especifica el el ROSA, ya esta listo.
    //
    if (color==trans) return;
       
    // Convertimos el color transparente al ROSA
    //
    for (int x=0;x<getWidth();x++)
    for (int y=0;y<getHeight();y++)
    {
        if (getPixel(x,y)==color) setPixel(x,y,trans);
    }
}    

void TMABitmap::bilinearStretch(const PMABitmap origen,int ox,int oy,int owidth,int oheight,
        int dx,int dy,int dwidth,int dheight)
{
    double fraction_x, fraction_y, one_minus_x, one_minus_y;
    int ceil_x, ceil_y, floor_x, floor_y;
    unsigned char red, green, blue;
    unsigned char b1, b2;
    int c1,c2,c3,c4;

    double nXFactor = (double)owidth/(double)dwidth;
    double nYFactor = (double)oheight/(double)dheight;
        
    for (int x = 0; x < dwidth; ++x)
    {
        for (int y = 0; y < dheight; ++y)
        {
            // Setup

            floor_x = (int)floor(x * nXFactor);
            floor_y = (int)floor(y * nYFactor);
            ceil_x = floor_x + 1;
            if (ceil_x >= owidth) ceil_x = floor_x;
            ceil_y = floor_y + 1;
            if (ceil_y >= oheight) ceil_y = floor_y;
            fraction_x = x * nXFactor - floor_x;
            fraction_y = y * nYFactor - floor_y;
            one_minus_x = 1.0 - fraction_x;
            one_minus_y = 1.0 - fraction_y;

            c1 = getpixel(origen->io_bmp,ox+floor_x, oy+floor_y);
            c2 = getpixel(origen->io_bmp,ox+ceil_x, oy+floor_y);
            c3 = getpixel(origen->io_bmp,ox+floor_x, oy+ceil_y);
            c4 = getpixel(origen->io_bmp,ox+ceil_x, oy+ceil_y);

            // Blue
            b1 = (unsigned char)(one_minus_x * getb(c1) + fraction_x * getb(c2));
            b2 = (unsigned char)(one_minus_x * getb(c3) + fraction_x * getb(c4));
            blue = (unsigned char)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

            // Green
            b1 = (unsigned char)(one_minus_x * getg(c1) + fraction_x * getg(c2));
            b2 = (unsigned char)(one_minus_x * getg(c3) + fraction_x * getg(c4));
            green = (unsigned char)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

            // Red
            b1 = (unsigned char)(one_minus_x * getr(c1) + fraction_x * getr(c2));
            b2 = (unsigned char)(one_minus_x * getr(c3) + fraction_x * getr(c4));            
            red = (unsigned char)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

            putpixel(io_bmp,dx+x,dy+y, makecol(red,green,blue));
        }
    }
}

#endif
