/* display.c
 *
 * Renders the displays.
 *
 * (c) 2006, Joseph Curtis
 */

#include <stdlib.h>
#include <stdio.h>

#include "display.h"
#include "world.h"

#ifndef x86
#include <pspdebug.h>
#include <pspthreadman.h>
//#define printf pspDebugScreenPrintf
#endif

/* The default display */
struct display *default_display;

int update_view(struct display *d, int v, void *data) {
  printf("update_view:\n");
  //  d->views[v].func(data);
  if(d->views[v].type == VIEW_MAIN) {
    printf("About to call update main!\n");
    update_main(d, data);
  } else if (d->views[v].type == VIEW_MENU) {
    update_menu(d, data);
  } else if (d->views[v].type == VIEW_MAP) {
    update_map(d, data);
  }

  /* blits the current view to the screen */
#ifndef x86
  printf("blitting to screen: (current view %d)\n", d->current_view);
  blitImageToScreen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, d->views[d->current_view].image, 0, 0);
  flipScreen();
#endif

  return 1;
}

int update(struct display *d, void *data) {
  printf("update:\n");
  return update_view(d, d->current_view, data);
}

int update_menu(struct display *d, void *data) {
#ifdef x86
  printf("update_menu:\n");
#endif
  return 1;
}

int update_map(struct display *d, void *data) {
  struct world *w = (struct world *)data;
  int i, j, c;

  for (j=0;j<w->height;j++) {
    for (i=0;i<w->width;i++) {
      switch(w->map[I(i, j, w->width)].image) {
      case 9:
	c = 0xFF00AA00;
	break;
      case 8:
	c = 0xFF0000BB;
	break;
      default:
	c = 0xFFFFFFFF;
      }
#ifndef x86
      fillImageRect(c, i*2, j*2, 2, 2, d->views[VIEW_MAP].image);
#endif
    }
  }
  

  return 1;
}

int update_main(struct display *d, void *data) {
  struct world * w = (struct world *)data;
  int vis_cellx, vis_celly;
  int vis_cellx1, vis_celly1;
  int x_offset, y_offset;
  int i, j, k, x=0, y=0;
  int blitx, blity;

  printf("update_main:\n");

#ifndef x86
  //  sceKernelDelayThread(3000000);
#endif

  //  print_world(w);

  // blit my stuff to my image then return.
  // we have the world and the coords of the top-left of the visible window.
  // determine which cells are visible or partially visible

  vis_cellx = w->vis_x / CELL_WIDTH;
  vis_celly = w->vis_y / CELL_HEIGHT;

  vis_cellx1 = 1 + ((w->vis_x + (VIS_WIDTH * CELL_WIDTH)) / CELL_WIDTH);
  vis_celly1 = 1 + ((w->vis_y + (VIS_HEIGHT * CELL_HEIGHT)) / CELL_HEIGHT);

  x_offset = w->vis_x - (vis_cellx * CELL_WIDTH);
  y_offset = w->vis_y - (vis_celly * CELL_HEIGHT);

  //  printf("vis_x: %d, vis_y: %d\n", w->vis_x, w->vis_y);
  //  printf("x: %d, y: %d, x1: %d, y1: %d\n", vis_cellx, vis_celly, vis_cellx1, vis_celly1);
  //  printf("x_offset: %d, y_offset: %d\n\n", x_offset, y_offset);


  for(j=vis_celly;j<vis_celly1;j++) {
    for(i=vis_cellx;i<vis_cellx1;i++) {
      //      printf("%d", w->map[I(i, j, w->width)].image);
      blitx = X(w->map[I(i, j, w->width)].image, GRAPH_WIDTH) * CELL_WIDTH; // in cells
      blity = Y(w->map[I(i, j, w->width)].image, GRAPH_WIDTH) * CELL_HEIGHT; // in cells
      //      printf("blitx: %d, blity: %d\n", blitx, blity);
#ifndef x86
      //      if (w->map[I(i, j, w->width)].image > -1)
      blitImageToImage(blitx, blity, CELL_WIDTH, CELL_HEIGHT, w->graphics,
		       (x*CELL_WIDTH) - x_offset, (y*CELL_HEIGHT) - y_offset,
		       d->views[VIEW_MAIN].image);
#endif      
      x++;
    }
    x=0;
    y++;
  }
  // end cell blitting
  printf("blitted cells\n");

  // check if a castle is in view and blit if necessary
  for(i=0;i<w->num_towns;i++) {
    if((w->towns[i].x >= vis_cellx && w->towns[i].x <= (vis_cellx + VIS_WIDTH)) && (w->towns[i].y >= vis_celly && w->towns[i].y <= (vis_celly + VIS_HEIGHT))) {
      blitx = X(w->towns[i].image, GRAPH_WIDTH) * CELL_WIDTH;
      blity = Y(w->towns[i].image, GRAPH_WIDTH) * CELL_HEIGHT;
      x = (w->towns[i].x * CELL_WIDTH) - w->vis_x;
      y = (w->towns[i].y * CELL_HEIGHT) - w->vis_y;
      printf("town blitx: %d, blity: %d, x: %d, y: %d\n", blitx, blity, x, y);
#ifndef x86
      blitImageToImage(blitx, blity, CELL_WIDTH * 2, CELL_HEIGHT * 2, 
		       w->graphics, x, y,
		       d->views[VIEW_MAIN].image);
#endif
    }
  }
  // end castling
  printf("blitted castles\n");
  
  // check if an army is in view and blit if necessary
  

  for (i=0;i<w->num_armies;i++) {
    if( (w->armies[i].a[w->armies[i].on_top].x >= vis_cellx && w->armies[i].a[w->armies[i].on_top].x <= (vis_cellx + VIS_WIDTH)) && (w->armies[i].a[w->armies[i].on_top].y >= vis_celly && w->armies[i].a[w->armies[i].on_top].y <= (vis_celly + VIS_HEIGHT)) ) {
      // yay, what a long condition list!
      
      blitx = X(w->armies[i].a[w->armies[i].on_top].type.t, ARMY_WIDTH)
	* TROOP_WIDTH;
      blity = Y(w->armies[i].a[w->armies[i].on_top].type.t, ARMY_WIDTH)
	* TROOP_HEIGHT;
      
      x = (w->armies[i].a[w->armies[i].on_top].x * CELL_WIDTH) - w->vis_x
	+ (CELL_WIDTH-TROOP_WIDTH) / 2;
      y = (w->armies[i].a[w->armies[i].on_top].y * CELL_HEIGHT) - w->vis_y
	+ (CELL_HEIGHT-TROOP_HEIGHT) / 2;
      
      //    printf("army blitx: %d, blity: %d, x: %d, y: %d\n", blitx, blity, x, y);

#ifndef x86

      //blitImageToImage(0, 0, 50, 50, w->army_graphics, 0, 0, d->views[VIEW_MAIN].image);

      blitAlphaImageToImage(blitx, blity, TROOP_WIDTH, TROOP_HEIGHT,
		       w->army_graphics, x, y, d->views[VIEW_MAIN].image);
#endif
      //      printf("blitted army:\n");
    }
  }
  // end armying
  printf("blitted armies\n");

  
  //beveled_box(0, SCREEN_HEIGHT - STATUS_BAR_HEIGHT, SCREEN_WIDTH, STATUS_BAR_HEIGHT, d->views[VIEW_MAIN].image);
  /* top border */
  //beveled_box(0, 0, SCREEN_WIDTH, 8, d->views[VIEW_MAIN].image);
  /* left border */
  //beveled_box(0, 8, 8, SCREEN_HEIGHT-STATUS_BAR_HEIGHT-1, d->views[VIEW_MAIN].image);
  /* right border */
  //beveled_box(SCREEN_WIDTH-8, 8, SCREEN_WIDTH-1, SCREEN_HEIGHT-STATUS_BAR_HEIGHT-1, d->views[VIEW_MAIN].image);


#ifndef x86
  /* the status bar */
  blitAlphaImageToImage(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, d->views[3].image, 0, 0, d->views[VIEW_MAIN].image);
  /* now put some text there */
  putText(16, (SCREEN_HEIGHT-STATUS_BAR_HEIGHT)+(STATUS_BAR_HEIGHT/2),
	    "FOOBAR!");
  printTextScreen(10, 10, "mofo", 0xFF000000);
#endif

  return 1;
}


// TODO: this properly, and frees!
int setup_default_display() {
  default_display = malloc(sizeof(struct display));
  default_display->current_view = 1;
  default_display->num_views = 3;
  default_display->views = malloc(sizeof(struct view) * 4);
  default_display->views[0].type = VIEW_MENU;
  default_display->views[1].type = VIEW_MAIN;
  default_display->views[2].type = VIEW_MAP;


#ifndef x86
  default_display->views[0].image = loadImage("images/MAIN.png");
  default_display->views[1].image = createImage(SCREEN_WIDTH, SCREEN_HEIGHT);
  default_display->views[2].image = loadImage("images/map.png");
  default_display->views[3].image = loadImage("images/border.png");
#endif

  return 1;
}

int destroy_default_display() {
#ifndef x86
  freeImage(default_display->views[0].image);
  freeImage(default_display->views[1].image);
  freeImage(default_display->views[2].image);
#endif
  free(default_display->views);
  free(default_display);
  return 1;
}

#ifndef x86
void beveled_box(int x, int y, int width, int height, Image *i) {
  /* black border */
  fillImageRect(0x00000000, x, y, width, height, i);
  fillImageRect(0xFFDDDDDD, x+1, y+1, width-1, height-1, i);
  fillImageRect(0xFF999999, x+3, y+3, width-3, height-3, i);
  fillImageRect(0xFFBBBBBB, x+3, y+3, width-6, width-6, i);
}
#endif


void putText(int x, int y, char * text) {
#ifndef x86
  printf("put_text:\n");
  printTextScreen(x, y, text, 0xFF000000);
#endif
}

