/*
 * Bg.c - Background support code
 * By: Odis
 */
#include <windows.h>
#include "main.h"

SPRITE *psprite; /* from game.c/h */

void bg_clean( BG *bg )
{
  if ( bg == NULL )
    return;
    
  if ( bg->bitmap )
   bg->bitmap = NULL;
   
  if ( bg->dynamic.starry != NULL )
   DISPOSE( bg->dynamic.starry );
   
   bg->color = 0;
   bg->width = 0;
   bg->height = 0;

   bg->simmune = 0;
   bg->stretch = 0;
   
   DISPOSE( bg );
}

void bg_draw( LEVEL *level, HDC hDC )
{
  BG *bg = NULL;

  if ( level == NULL || ((bg = level->bg) == NULL) )
   return;

  /* draw bg */
  if ( bg->bitmap != NULL )
  {
   if ( (bg->width < PRG_WIDTH) || (bg->height < PRG_HEIGHT) ) /* paint in black first! */
   {
     RECT rect = { 0, 0, PRG_WIDTH, PRG_HEIGHT };
     HBRUSH brush = CreateSolidBrush(RGB(0,0,0));
     FillRect(hDC, &rect, brush);
     DeleteObject(brush);
     
     HDC hMemDC = CreateCompatibleDC(hDC);
     HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, bg->bitmap->bitmap);
     
     POINT pos;
     pos.x = (PRG_WIDTH/2) -  (bg->bitmap->width/2);
     pos.y = (PRG_HEIGHT/2) - (bg->bitmap->height/2);
     
     BitBlt(hDC, pos.x, pos.y, bg->bitmap->width, bg->bitmap->height, hMemDC, 0, 0, SRCCOPY);
     
     SelectObject(hMemDC, hOldBitmap);
     DeleteDC(hMemDC);
   }
   else if ( bg->stretch == TRUE && (bg->simmune == FALSE) ) /* stretch background if its not immune */
     Draw(bg->bitmap, hDC, level->pos.x, level->pos.y, FALSE, TRUE);
   else
     Draw(bg->bitmap, hDC, level->pos.x, level->pos.y, FALSE, FALSE);
  }
  else
  {
     /* fill this fellow with a color */
     RECT rect = { 0, 0, bg->width, bg->height };
     HBRUSH brush = CreateSolidBrush(bg->color);
     FillRect(hDC, &rect, brush);
     DeleteObject(brush);
  }

 if ( bg->type == STARRY && bg->dynamic.starry != NULL )
 {
  int i;
  for ( i = 0; i < bg->dynamic.starry->stars; i++ )
   SetPixel(hDC, bg->dynamic.starry->pstars[i].x, bg->dynamic.starry->pstars[i].y, bg->dynamic.starry->star_colors[i]);
 }
}

/* for animated bg's */
void bg_update( LEVEL *level )
{
 BG *bg = level->bg;
 
 if ( bg->type == IMAGE )
 {
   if ( ((bg->width < PRG_WIDTH) || (bg->height < PRG_HEIGHT)) && (bg->simmune == FALSE) )
    bg->stretch = TRUE;
   
   if ( psprite != NULL && level->num > 0)
   {
        POINT stick = { 0, 0 };
        stick.x        = psprite->position.x; /* position of stickman */
        stick.y        = psprite->position.y;

        POINT pos = level->pos; /* position of top left corner of game screen */
        POINT bounds; /* the lower right corner of the map*/
        POINT size;

        size.x = PRG_WIDTH;
        size.y = PRG_HEIGHT;
        
        bool scrollx = FALSE, scrolly = FALSE;

        /* do we need x? */
        if ( (pos.x == 0 && stick.x > size.x/2) || (pos.x == level->bounds.right-size.x && (stick.x-level->pos.x) < size.x/2) )
         scrollx = TRUE;
        else if ( pos.x != 0 && pos.x != level->bounds.right-size.x )
         scrollx = TRUE;
         
        /* do we need y? */
        if ( (pos.y == 0 && stick.y > size.y/2) || (pos.y == level->bounds.bottom-size.y && (stick.y-level->pos.y) < size.y/2) )
         scrolly = TRUE;
        else if ( pos.y != 0 && pos.y != level->bounds.bottom-size.y )
         scrolly = TRUE;


       /* scrolling...*/
       /* scroll left/right */
       if ( scrollx == TRUE )
        if ( stick.x > size.x/2 ) /* over half game screen? */
          pos.x += psprite->velocity.x;
        else if ( stick.x < size.x/2 )
          pos.x += psprite->velocity.x; /* velocity should be negative */

        /* scroll up/down */
       if ( scrolly == TRUE )
        if ( stick.y > size.y/2 ) /* over half game screen? */
          pos.y += psprite->velocity.y;
        else if ( stick.y < size.y/2 )
          pos.y += psprite->velocity.y; /* velocity should be negative */

        /* fail-safes */
        if ( pos.x < 0 )
         pos.x = 0;
        else if ( pos.x+PRG_WIDTH > level->bounds.right )
         pos.x = level->bounds.right-PRG_WIDTH;

        if ( pos.y < 0 )
         pos.y = 0;
        else if ( pos.y+PRG_HEIGHT > level->bounds.bottom )
         pos.y = level->bounds.bottom-PRG_HEIGHT;

         level->pos.x = pos.x;
         level->pos.y = pos.y;
         
         SetPosition( psprite, stick );
   }
 }



  /* random change shades */
 if ( bg->type == STARRY && bg->dynamic.starry != NULL )
 {
  int rgb, i;

  for ( i = 0; i < bg->dynamic.starry->stars; i++ )
  {
    if (random(0,bg->dynamic.starry->delay) == 2)
    {
      rgb = random( 0, 255 );
      bg->dynamic.starry->star_colors[i] = RGB(rgb,rgb,rgb);
    }
  }
 }
}

/* helppers */
BG *bg_from_bitmap( BMP *bmp )
{
  BG *bg;

  if ( bmp == NULL )
   return NULL;

  /* alloc mem */
  CREATE( bg, BG, 1);
  
  bg->bitmap = bmp;
  bg->height = bmp->height;
  bg->width  = bmp->width;
  bg->color  = 0;
  bg->simmune = FALSE; /* not immune unless specified otherwise */
  
  if ( (bg->width < PRG_WIDTH) || (bg->height < PRG_HEIGHT) )
   bg->stretch = TRUE;
  else
   bg->stretch = FALSE;
  
  return bg;
}

BG *bg_from_init( int width, int height, COLORREF color )
{
   BG *bg;
   
   if ( width < 1 || height < 1 )
    return NULL;
    
   CREATE( bg, BG, 1 );
   
   bg->width  = width;
   bg->height = height;
   bg->stretch = FALSE;
   bg->bitmap = NULL;
   bg->color  = color;
   bg->simmune = FALSE;
   
   return bg;
}

void init_starry( BG *bg, int stars, int delay )
{
  int i;
  
  if ( bg == NULL )
   return;

  if ( bg->dynamic.starry != NULL )
   return;
   
  STARRY_DATA *star;
  CREATE( star, STARRY_DATA, 1 );
   
  star->stars = URANGE(10,stars,MAX_STARS);
  star->delay = delay;
  
  for ( i = 0; i < star->stars; i++ )
  {
     star->pstars[i].x = random(0, bg->width );
     star->pstars[i].y = random(0, bg->height );
     star->star_colors[i] = RGB(128,128,128);
  }
  bg->dynamic.starry = star;
}