/****************************************************************
    class base_image, BY AHARON HILLEL.
    The basic sprite-class.
    sprites reside in array of (RLE_SPRITE *)
    gcc version 3.2 (mingw special 20020817-1)
    ALLEGRO VERSION: 4.1.12 (WIP)
    ALLEGRO DATE:    2003-11-10
****************************************************************/
#include "baseimage.h"
/*  To use this class, all sprites should reside in:  */
/*  RLE_SPRITE *sprites_array[LAST_SPRITE] array.     */
base_image::base_image()
{
    index = x = y = x_start = y_start = z = -1;  //  set to invalid image.
    visible = use_bg = G_FALSE;
    data = NULL;
    dest = bg = NULL;
};

base_image::base_image(RLE_SPRITE **dt, const int s_index)
{
    data = dt;
    index = s_index;  //  set to invalid image.
    visible = use_bg = G_FALSE;
    dest = bg = NULL;
};

base_image::base_image(RLE_SPRITE **dt, BITMAP *dst, const int sprite_index)
{
    index = sprite_index;
    data = dt;
    visible = use_bg = G_FALSE;
    x = y = x_start = y_start -1;
    z = 0;
    dest = dst;
    bg = NULL;
};

base_image::base_image(RLE_SPRITE **dt, BITMAP *dst, const int pos_x, const int pos_y, const int sprite_index, const int bg_flag, const int d)
{
    const RLE_SPRITE *sprite;
    data = dt;
    use_bg = bg_flag;
    visible  = d;
    index = sprite_index;
    sprite = data[index];
    x = x_start = pos_x;
    y = y_start = pos_y;
    z = 0;
    dest = dst;
    bg = NULL;


    if(visible)
    { //  get memory to save background, and save with blit from screen.
      if(use_bg)
      {
        bg = create_bitmap(sprite->w, sprite->h);
        if(bg)
          blit(dest, bg, x, y, 0, 0 , sprite->w, sprite->h);
      }

      draw_rle_sprite(dest, sprite, x, y);  //  Draw image to screen.
    }
};

base_image::base_image(RLE_SPRITE **dt, BITMAP *dst, const int pos_x, const int pos_y, const int z_order, const int sprite_index, const int bg_flag, const int d)
{
    const RLE_SPRITE *sprite;
    index = sprite_index;
    data = dt;
    sprite = data[index];
    visible = d;
    use_bg = bg_flag;
    x = x_start = pos_x;
    y = y_start = pos_y;
    z = z_order;
    dest = dst;
    bg = NULL;

    if(visible)
    { //  get memory to save background, and save with blit from screen.
      if(use_bg)
      {
        bg = create_bitmap(sprite->w, sprite->h);
        if(bg)
          blit(dest, bg, x, y, 0, 0 , sprite->w, sprite->h);
      }

      draw_rle_sprite(dest, sprite, x, y);  //  Draw image to screen.
    }
};

base_image::base_image(const base_image &other)  // COPY constructor.
{
    const RLE_SPRITE *sprite;
    data = other.data;
    use_bg = other.use_bg;
    visible = other.visible;
    index = other.index;
    sprite = data[index];

    dest = other.dest;
    x = other.x;
    y = other.y;
    x_start = other.x_start;
    y_start = other.y_start;
    z = other.z;

    if(other.bg)
    {
      bg = create_bitmap(sprite->w, sprite->h);
      if(bg)
        blit(other.bg, bg, 0, 0, 0, 0 , sprite->w, sprite->h);
    }
    else bg = NULL;
};

void base_image::set_sprite_index(const int new_index)
{
    RLE_SPRITE *sprite = data[index];
    RLE_SPRITE *new_sprite;

    if(new_index >= 0)
    {
      new_sprite = data[new_index];

      if((sprite->h != new_sprite->h) || (sprite->w != new_sprite->w))
      {
       if(bg)
         destroy_bitmap(bg);

       bg = NULL;  //  Will recover at first draw of new sprite.
      }
    }

    index = new_index;
};

int base_image::inside(const int left_x, const int top_y, const int right_x, const int bt_y)
{   // Test if sprite inside a rectangular area.
    const RLE_SPRITE *sprite;

    if(index < 0)
      return G_FALSE;

    sprite = data[index];
    if(x < left_x) return G_FALSE;
    if(x+sprite->w > right_x) return G_FALSE;

    if(y < top_y) return G_FALSE;
    if(y+sprite->h > bt_y) return G_FALSE;

    return G_TRUE;
};

int base_image::point_inside(const int pos_x, const int pos_y)
{
    if(index < 0)
      return G_FALSE;

    if(pos_x < x) return G_FALSE;
    if(pos_y < y) return G_FALSE;
    
    const RLE_SPRITE *sprite = data[index];
    if(pos_x > x+sprite->w) return G_FALSE;
    if(pos_y > y+sprite->h) return G_FALSE;
    
    return G_TRUE;
}

int base_image::collision(const int pos_x, const int pos_y, const RLE_SPRITE &other)
{
    const RLE_SPRITE *sprite;

    if(index < 0)
      return G_FALSE;

    sprite = data[index];
    if(x+sprite->w < pos_x) return G_FALSE;
    if(x > pos_x+other.w) return G_FALSE;

    if(y+sprite->h < pos_y) return G_FALSE;
    if(y > pos_y+other.h) return G_FALSE;

    return G_TRUE;
};

int base_image::collision_ex(const int pos_x, const int pos_y, const int z_order, const RLE_SPRITE &other)
{
    if(z != z_order)
      return G_FALSE;

    return collision(pos_x, pos_y, other);
};

int base_image::draw()
{
    const RLE_SPRITE *sprite;

    if(index < 0)
      return G_FALSE;

    visible = G_TRUE;
    sprite = data[index];
    if(use_bg)
    { //  get memory to save background, and save with blit from screen.
      if(!bg)
        bg = create_bitmap(sprite->w, sprite->h);

      if(bg)  // Got mem? save bg from screen.
        blit(dest, bg, x, y, 0, 0 , sprite->w, sprite->h);
    }

    draw_rle_sprite(dest, sprite, x, y);  //  Draw image to screen.

    return G_TRUE;
}

int base_image::remove()
{
    const RLE_SPRITE *sprite;

    if(index < 0)
      return G_FALSE;

    sprite = data[index];

    if(visible)
    {
      if(use_bg)
      {
        if(bg)  //  restore background
          blit(bg,dest,0 , 0, x, y, sprite->w, sprite->h);
      }
      else    // fill a black rectangle.
        rectfill(dest, x, y, x+sprite->w, y+sprite->h, 0);
    }

    visible = G_FALSE;
}

int base_image::erase()
{
    const RLE_SPRITE *sprite;

    if(index < 0)
      return G_FALSE;

    sprite = data[index];
    //  Draw a black rectangle.
    rectfill(dest, x, y, x+sprite->w, y+sprite->h, 0);

    visible = G_FALSE;
}

int base_image::set_pos(const int new_x, const int new_y, const int d)
{
    x = new_x; y = new_y;

    if(x_start < 0)
    {
      x_start = x;
      y_start = y;
    }

    visible = d;

    if(visible)
      return draw();

    return G_TRUE;
};

int base_image::set_pos_ex(const int new_x, const int new_y, const int new_z, const int d)
{
    x = new_x; y = new_y; z = new_z;

    if(x_start < 0)
    {
      x_start = x;
      y_start = y;
    }

    visible = d;

    if(visible)
      return draw();
    return G_TRUE;
};

int base_image::move(const int new_x, const int new_y)
{
    remove();
    x = new_x; y = new_y;

    if(x_start < 0)
    {
      x_start = x;
      y_start = y;
    }

    return draw();
};

int base_image::move_ex(const int new_x, const int new_y, const int new_z)
{
    remove();
    x = new_x; y = new_y; z = new_z;

    if(x_start < 0)
    {
      x_start = x;
      y_start = y;
    }

    return draw();
};

int base_image::go_to_start_pos(void)
{
    if(x_start < 0)
      return G_FALSE;

    if(visible)
      remove();

    if(bg)
    { //  Recover on first draw.
      delete(bg);
      bg = NULL;
    }

    x = x_start; y = y_start;

    if(visible)
      return draw();
};

//  Virtual functions of base class.
base_image::~base_image()  //  destructor
{
    if(bg)
       destroy_bitmap(bg);
};

int base_image::kill(void)
{
    set_sprite_index(-1);
    return G_TRUE;
};

int base_image::action(void)
{
    return G_TRUE;
};
//------------  END  of base_image class