#include "raine.h"
#include "blit.h"
#include "SDL.h"
#include "games.h"
#include "video/tilemod.h"
#include "compat2.h"
#include "ingame.h"
#include "profile.h"
#include "gen_conv.h"
#include "video/res.h"

/* For now this module uses SDL AND Allegro */

extern int disp_screen_x, disp_screen_y;

extern SDL_Surface *get_sdl_surface(BITMAP *b); // display.c
UINT32 pause_time;
int key_data[MAX_LAYER_INFO]=
{
   SDLK_F5,
   SDLK_F6,
   SDLK_F7,
   SDLK_F8,
   SDLK_F9,
   SDLK_F10,
   SDLK_F12,
   SDLK_F12,
   SDLK_F12,
   SDLK_F12,
   SDLK_F12,
   SDLK_F12,
   SDLK_F12,
   SDLK_F12,
   SDLK_F12,
   SDLK_F12,
};

typedef struct RAINEBITMAP
{
   int xfull;		// Full bitmap width
   int yfull;		// Full bitmap height
   int xtop;		// X Offset of viewable area
   int ytop;		// Y offset of viewable area
   int xview;		// Viewable bitmap width
   int yview;		// Viewable bitmap height
} RAINEBITMAP;

RAINEBITMAP GameScreen;

static int destx, desty, xxx, yyy, xoff2, yoff2;

static void do_save_screen(void)
{
   UINT8 full_name[256];
   UINT8 file_name[32];

   raine_cfg.req_save_screen = 0;

   /*

   first try gamename.pcx

   */

   sprintf(file_name, "%s.pcx", current_game->main_name);

   sprintf(full_name, "%s%s", dir_cfg.screen_dir, file_name);

   /*

   otherwise, find the next gamename_NNN.pcx (or gamenNNN.pcx)

   */

   while( exists(full_name) ){

      if(dir_cfg.last_screenshot_num > 999)

	 return;

      if(dir_cfg.long_file_names)

	 sprintf(file_name, "%s_%03d.pcx", current_game->main_name, dir_cfg.last_screenshot_num++);

      else

	 sprintf(file_name, "%.5s%03d.pcx", current_game->main_name, dir_cfg.last_screenshot_num++);

      sprintf(full_name, "%s%s", dir_cfg.screen_dir, file_name);

   };

   save_pcx(full_name, GameViewBitmap, pal);

   print_ingame(120, "Screen Saved to %s", file_name);
}

SDL_Rect area_overlay,area2;

void ReClipScreen(void)
{
   // clip x

  int oldxview,oldyview;

  oldxview = GameScreen.xview;
  oldyview = GameScreen.yview;
  if (display_cfg.stretch && GameScreen.xview > 0) {
    if (display_cfg.stretch == 1) {
      GameScreen.xview = stretchx;
      GameScreen.yview = stretchy;
    } else {
      GameScreen.xview = disp_screen_x;
      GameScreen.yview = disp_screen_y;
    }
  }

  if(GameScreen.xview < disp_screen_x){
    destx = (disp_screen_x - GameScreen.xview)>>1;
  }
  else{
    destx = 0;
  }
  if (oldxview < disp_screen_x) {
    // We can't write outside the game bitmap so we have to use oldxview
    xxx = oldxview;
    xoff2 = GameScreen.xtop;
  } else {
    // If the game bitmap is bigger than the screen, then no risk (if stretched)
    if(GameScreen.xview <= disp_screen_x){
      xxx = oldxview;
      xoff2 = GameScreen.xtop;
    } else {
      xxx = disp_screen_x;
      xoff2 = GameScreen.xtop + ((GameScreen.xview - disp_screen_x)>>1);
    }
  }

  // clip y

  if(GameScreen.yview < disp_screen_y){
    desty = (disp_screen_y - GameScreen.yview)>>1;
  }
  else{
    desty = 0;
  }
  if(oldyview < disp_screen_y){
    yyy = oldyview;
    yoff2 = GameScreen.ytop;
  } else {
    if(GameScreen.yview <= disp_screen_y){
      yyy = oldyview;
      yoff2 = GameScreen.ytop;
    } else {
      yyy = disp_screen_y;
      yoff2 = GameScreen.ytop + ((GameScreen.yview - disp_screen_y)>>1);
    }
  }

  GameScreen.xview = oldxview;
  GameScreen.yview = oldyview;
}

void InitDrawPaused(void)
{
}

void EndDrawPaused() {}

void DrawPaused() {}

static void SetScreenBitmap(int xfull, int yfull, int xtop, int ytop, int xview, int yview)
{
   const VIDEO_INFO *vid_info;

   vid_info = current_game->video_info;

   display_cfg.rotate = 0;
   display_cfg.flip = 0;

   if(vid_info->flags & VIDEO_ROTATABLE){

      /*

      check if we use the game rotation

      */

      if(!display_cfg.no_rotate)

	 display_cfg.rotate = VIDEO_ROTATE( vid_info->flags );

      /*

      check if we use the game flipping

      */

      if(!display_cfg.no_flip)

	 display_cfg.flip = VIDEO_FLIP( vid_info->flags );

      /*

      add user rotation

      */

      display_cfg.rotate += display_cfg.user_rotate;
      display_cfg.rotate &= 3;

      /*

      add user flipping

      */

      display_cfg.flip ^= display_cfg.user_flip;

   }

   switch(display_cfg.rotate){
   case 0x00:
      GameScreen.xfull=xfull;
      GameScreen.yfull=yfull;
      GameScreen.xtop =xtop;
      GameScreen.ytop =ytop;
      GameScreen.xview=xview;
      GameScreen.yview=yview;
   break;
   case 0x01:
      GameScreen.xfull=yfull;
      GameScreen.yfull=xfull;
      GameScreen.xtop =ytop;
      GameScreen.ytop =xtop;
      GameScreen.xview=yview;
      GameScreen.yview=xview;
   break;
   case 0x02:
      GameScreen.xfull=xfull;
      GameScreen.yfull=yfull;
      GameScreen.xtop =xtop;
      GameScreen.ytop =ytop;
      GameScreen.xview=xview;
      GameScreen.yview=yview;
   break;
   case 0x03:
      GameScreen.xfull=yfull;
      GameScreen.yfull=xfull;
      GameScreen.xtop =ytop;
      GameScreen.ytop =xtop;
      GameScreen.xview=yview;
      GameScreen.yview=xview;
   break;
   }

   check_tile_rotation();

   /*

   these modes double the image size (it's simpler to consider
   them as halving the display resolution)

   */

   if (use_scale2x) {
     disp_screen_x /= 2;
     disp_screen_y /= 2;
   } else if(display_cfg.pixel_double){

     if(display_cfg.pixel_double == 1){

       disp_screen_x /= 2;
       disp_screen_y /= 2;

     }
     else{

       disp_screen_x /= 2;

     }

   }
   else{

     if(display_cfg.bpp == 8){

       if(display_cfg.eagle_fx){

	 disp_screen_x /= 2;
	 disp_screen_y /= 2;

       }

     }

   }

   ReClipScreen();
}

void SetupScreenBitmap(void)
{
   const VIDEO_INFO *vid_info;

   vid_info = current_game->video_info;

   SetScreenBitmap(
      vid_info->screen_x + vid_info->border_size + vid_info->border_size,
      vid_info->screen_y + vid_info->border_size + vid_info->border_size,
      vid_info->border_size,
      vid_info->border_size,
      vid_info->screen_x,
      vid_info->screen_y
   );

   GameBitmap = sdl_create_bitmap_ex(internal_bpp(display_cfg.bpp), GameScreen.xfull, GameScreen.yfull);
   // GameBitmap = sdl_create_overlay(GameScreen.xfull, GameScreen.yfull);
   // GameBitmap = create_system_bitmap( GameScreen.xfull, GameScreen.yfull);
   GameViewBitmap = sdl_create_sub_bitmap(GameBitmap, GameScreen.xtop, GameScreen.ytop, GameScreen.xview, GameScreen.yview);

   if (sdl_overlay) {
     double ratio1 = display_cfg.screen_x*1.0/xxx;
     double ratio2 = display_cfg.screen_y*1.0/yyy;
     int xxx2,yyy2,destx2,desty2;
     if (ratio1 < ratio2) {
       xxx2 = display_cfg.screen_x;
       yyy2 = ratio1 * yyy;
       destx2 = 0;
       desty2 = (display_cfg.screen_y - yyy2)/2;
     } else {
       yyy2 = display_cfg.screen_y;
       xxx2 = ratio2 * xxx;
       desty2 = 0;
       destx2 = (display_cfg.screen_x - xxx2) /2;
     }
     area_overlay.x = destx2;
     area_overlay.y = desty2;
     area_overlay.w = xxx2;
     area_overlay.h = yyy2;
   }

   area2.x = destx; // x2;
   area2.y = desty; // y2;
   area2.w = xxx;
   area2.h = yyy;

   clear(GameViewBitmap);

   RefreshBuffers=1;
}

void DestroyScreenBitmap(void)
{
   sdl_destroy_bitmap(GameBitmap);
   destroy_bitmap(GameViewBitmap);
}

extern void *old_draw; // dlg_sound

static void raine_fast_blit(BITMAP *source, BITMAP *dest, UINT32 x1, UINT32 y1, UINT32 x2, UINT32 y2, UINT32 w, UINT32 h)
{
  SDL_Rect area1;
  int ret;

  if (sdl_overlay) {
    // convert source to yuy2 format in the overlay
    unsigned char *src,*dest;
    int y;
    SDL_LockYUVOverlay(sdl_overlay);
    for (y=0; y<h; y++) {
      src = GameBitmap->line[y+y1]+x1*2;
      dest = sdl_overlay->pixels[0]+y*sdl_overlay->pitches[0];
      mmx_rgb565_yuyv(dest, src, w, 1, 0, 0);
    }
    SDL_UnlockYUVOverlay(sdl_overlay);

    SDL_DisplayYUVOverlay(sdl_overlay,&area_overlay);
  } else { // no overlay, classical blit

    SDL_Surface *s1 = get_sdl_surface(source),*s2 = get_sdl_surface(dest);
    area1.x = x1;
    area1.y = y1;
    area1.w = w;
    area1.h = h;

    ret = SDL_BlitSurface(s1, &area1, s2, &area2);
    if (ret) printf("got %d\n",ret);
    SDL_UpdateRects(s2,1,&area2);
  }
}

static void update_screen_palette(PALETTE palette)
{
  int ret;
  if (display_cfg.bpp != 8) return;
#ifdef RDTSC_PROFILE
   if(raine_cfg.show_fps_mode>2){
      ProfileStop(PRO_BLIT);
      ProfileStart(PRO_PAL);
   }
#endif

   ret = SDL_SetColors(get_sdl_surface(GameBitmap),(SDL_Color*)palette,0,256);

#ifdef RDTSC_PROFILE
   if(raine_cfg.show_fps_mode>2){
      ProfileStop(PRO_PAL);
      ProfileStart(PRO_BLIT);
   }
#endif
}

void DrawNormal(void)
{
  UINT16 i;
   /*

   save screenshots now (before we overwrite the image)

   */
  if (old_draw) return;

   /*

   scroll game screen

   */

   if (raine_cfg.req_pause_scroll) {
     if(raine_cfg.req_pause_scroll & 1)
        if(yoff2 > GameScreen.ytop)
  	  yoff2--;

     if(raine_cfg.req_pause_scroll & 2)
        if((yoff2 + disp_screen_y) < (GameScreen.ytop + GameScreen.yview))
	  yoff2++;

     if(raine_cfg.req_pause_scroll & 4)
        if(xoff2 > GameScreen.xtop)
	  xoff2--;

     if(raine_cfg.req_pause_scroll & 8)
        if((xoff2 + disp_screen_x) < (GameScreen.xtop + GameScreen.xview))
	  xoff2++;

     raine_cfg.req_pause_scroll = 0;
   }

   if(raine_cfg.req_save_screen == 1)
      do_save_screen();

   /*

   draw the ingame 'interface' (message list, fps)

   */

   overlay_ingame_interface();

   /*

   update host (pc) palette

   */

   update_screen_palette(pal);

   /*

   blit image to host (pc) videoram

   */

   raine_fast_blit(GameBitmap, screen, xoff2, yoff2, destx, desty, xxx, yyy);
}

void clear_game_screen(int pen)
{
  int x,y,len;
  switch(display_cfg.bpp) {
  case 8:
    len = GameViewBitmap->w;
    for (y=0; y<GameViewBitmap->h; y++)
      memset(GameViewBitmap->line[y],pen,len);
    break;
  case 15:
  case 16:
    len = GameViewBitmap->w*2;
    pen = (pen & 0xffff) | (pen<<16);
    for (y=0; y<GameViewBitmap->h; y++) {
      unsigned char *src = GameViewBitmap->line[y];
      for (x=0; x<len; x+= 4) {
	WriteLong(&src[x],pen);
      }
    }
    break;
  case 32:
    len = GameViewBitmap->w*4;
    for (y=0; y<GameViewBitmap->h; y++) {
      for (x=0; x<len; x+= 4) {
	WriteLong(GameViewBitmap->line[y]+x,pen);
      }
    }
    break;
  }
}

void get_screen_coordinates(int *Xoff2,int *Yoff2, int *Destx, int *Desty, int *Xxx, int *Yyy){
  *Xoff2 = xoff2;
  *Yoff2 = yoff2;
  *Xxx = xxx;
  *Yyy = yyy;
  *Destx = destx;
  *Desty = desty;
}

void reset_triple_buffer(void)
{
}

