// Necklace of the Eye v3.0
// roguelike frontend
// Copyright (C) 2010-2011 Zeno Rogue, see 'noteye.h' for details

int outscr;

void Screen::setSize(int x, int y) {
  sx = x; sy = y;
  v.resize(sx * sy);
  for(int i=0; i<sx*sy; i++) v[i] = 0;
  }

Screen* newScreen(int x, int y) {
  Screen *s = new Screen;
  s->setSize(x, y);
  return s;
  }

void Screen::write(int x, int y, const char *buf, Font *f, int color) {
  while(*buf) {
    int& c(get(x,y));
    c = addRecolor(f->ti[(unsigned char) (*buf)], color, recDefault);
    buf++; x++;
    }
  }

int& Screen::get(int x, int y) {
  if(x < 0 || x >=sx || y < 0 || y >= sy) return outscr;
  return v[y*sx+x];
  }

// --- drawing screen ---

Image *itl;

void drawTileImage(SDL_Surface *s, int x, int y, int tx, int ty, TileImage *TI) {
//  printf("trans = %08x\n", TI->trans);
  #ifdef USEBLITS
  if(tx == TI->sx && ty == TI->sy) {
    SDL_SetColorKey(TI->i->s, SDL_SRCCOLORKEY, TI->trans);
    SDL_Rect srcrect;
    TI->i->setLock(false); itl->setLock(false);
    srcrect.x = TI->ox; srcrect.y = TI->oy; srcrect.w = tx; srcrect.h = ty;
    SDL_Rect destrect;
    destrect.x = x; destrect.y = y;
    
    if(TI->trans == transAlpha) {
      SDL_SetAlpha(TI->i->s, SDL_SRCALPHA | SDL_RLEACCEL, 128);
      }
    else
      SDL_SetAlpha(TI->i->s, 0, 0);
    
    SDL_BlitSurface(TI->i->s, &srcrect, s, &destrect);
    }
  else
  #endif
  {
  TI->i->setLock(true); itl->setLock(true);
  int otx = tx, oty = ty, tox = TI->ox, toy = TI->oy;
  if(ty<0 || tx<0) printf("F tx=%3d ty=%3d tox=%3d toy=%3d\n", otx, oty, tox, toy);
  if(tx<0) { otx = -tx; x += tx; tox += TI->sx-1; }
  if(ty<0) { oty = -ty; y += ty; toy += TI->sy-1; }
  if(ty<0 || tx<0) printf("T tx=%3d ty=%3d tox=%3d toy=%3d\n", otx, oty, tox, toy);
  for(int ay=0; ay<oty; ay++) for(int ax=0; ax<otx; ax++) {
    int cy = TI->sy*ay/ty;
    int cx = TI->sx*ax/tx;
    int pix = qpixel(TI->i->s, tox + cx, toy + cy);
    if(tx<0 || ty<0) printf("%d,%d => %d,%d (%d,%d)\n", ax,ay, tox+cx, toy+cy, cx,cy);
    if(TI->trans == transAlpha) {
      alphablend(qpixel(s, x+ax, y+ay), pix);
      }
    else if(!istrans(pix, TI->trans)) 
      qpixel(s, x+ax, y+ay) = pix;
    }
  }
  }

void drawTile(SDL_Surface *s, int x, int y, int tx, int ty, int c) {
  if(c == 0) return;

  Get(TileImage, TI, c);
  if(TI) drawTileImage(s, x, y, tx, ty, TI);

  Get(TileMerge, TM, c);
  if(TM) {
    drawTile(s, x, y, tx, ty, TM->t1);
    drawTile(s, x, y, tx, ty, TM->t2);
    }

  Get(TileTransform, TT, c);
  if(TT) {
    x += tx * TT->dx / 1440;
    y += ty * TT->dy / 1440;
    tx = tx * TT->sx / 1440;
    ty = ty * TT->sy / 1440;
    drawTile(s, x, y, tx, ty, TT->t1);
    }

  Get(TileFill, TF, c);
  if(TF) {
    int col = TF->color;
    itl->setLock(true);
    
    if(TF->alpha == 0xffffff) {
      SDL_Rect dstrect;
      dstrect.x = x; dstrect.y = y; dstrect.w = tx; dstrect.h = ty;
      SDL_FillRect(s, &dstrect, col);
      }
    else if(TF->alpha == 0x808080) {
      itl->setLock(true);
      for(int ax=0; ax<tx; ax++) for(int ay=0; ay<ty; ay++) 
        mixcolor(qpixel(s, x+ax, y+ay), col);
      }
    else {
      for(int ax=0; ax<tx; ax++) for(int ay=0; ay<ty; ay++) 
        mixcolorAt(qpixel(s, x+ax, y+ay), col, TF->alpha);
      }
    }
  }

// --- lua

#ifdef USELUA
int lh_newScreen(lua_State *L) {
  checkArg(L, 2, "newscreen");
  Screen *s = newScreen(luaInt(1), luaInt(2));
  return retObject(L, s);
  }

int lh_scrwrite(lua_State *L) {
  checkArg(L, 6, "scrwrite");
  luaO(1, Screen)->write(luaInt(2), luaInt(3), luaStr(4), luaO(5, Font), luaInt(6));
  return 0;
  }

int lh_scrget(lua_State *L) {
  checkArg(L, 3, "scrget");
  return retInt(L, luaO(1, Screen)->get(luaInt(2), luaInt(3)));
  }

int lh_scrset(lua_State *L) {
  checkArg(L, 4, "scrset");
  int& C ( luaO(1, Screen)->get(luaInt(2), luaInt(3)) );
  C = luaInt(4);
  return 0;
  }

int lh_scrsetsize(lua_State *L) {
  checkArg(L, 3, "scrsetsize");
  luaO(1, Screen)->setSize(luaInt(2), luaInt(3));
  return 0;
  }

int lh_scrgetsize(lua_State *L) {
  checkArg(L, 1, "scrgetsize");
  Screen *scr = luaO(1, Screen);
  lua_newtable(L);
  setfield(L, "x", scr->sx);
  setfield(L, "y", scr->sy);
  return 1;
  }

int lh_scrcopy(lua_State *L) {
  checkArg(L, 9, "scrcopy");
  Screen *srcS = luaO(1, Screen);
  int srcX = luaInt(2);
  int srcY = luaInt(3);
  
  Screen *tgtS = luaO(4, Screen);
  int tgtX = luaInt(5);
  int tgtY = luaInt(6);
  
  int SX = luaInt(7);
  int SY = luaInt(8);
  
  for(int x=0; x<SX; x++) for(int y=0; y<SY; y++) {
    int& C1(srcS->get(srcX+x, srcY+y));
    int& C2(tgtS->get(tgtX+x, tgtY+y));
    lua_pushvalue(L, -1);
    lua_pushinteger(L, C1);
    lua_pushinteger(L, srcX+x);
    lua_pushinteger(L, srcY+y);
    
    if (lua_pcall(L, 3, 1, 0) != 0) {
      fprintf(errfile, "error running scrcopy: %s\n", lua_tostring(L, -1));
      halt();
      }

    C2 = luaInt(-1);
    lua_pop(L, 1);
    }
  
  return 0;
  }

int lh_scrfill(lua_State *L) {
  checkArg(L, 6, "scrfill");
  
  Screen *tgtS = luaO(1, Screen);
  int tgtX = luaInt(2);
  int tgtY = luaInt(3);
  
  int SX = luaInt(4);  
  int SY = luaInt(5);
  
  int C = luaInt(6);
  
  for(int x=0; x<SX; x++) for(int y=0; y<SY; y++) {
    tgtS->get(tgtX+x, tgtY+y) = C;
    }
  
  return 0;
  }

int lh_scrsave(lua_State *L) {
  Screen *srcS = luaO(1, Screen);
  const char *s = luaStr(2);
  int mode = luaInt(3);
  FILE *f = fopen(s, "wt");
  if(!f) {
    fprintf(errfile, "could not save file '%s'\n", s);
    return 0;
    }

  int lcolor = getCol(srcS->get(0,0)) & 0xFFFFFF;

  fprintf(f, 
    mode ? "[tt][color=#%06x]" :
    "<html>\n"
    "<head>\n"
    "<meta name=\"generator\" content=\"Necklace of the Eye\">\n"
    "<title>HTML Screenshot</title>\n"
    "</head>\n"
    "<body bgcolor=#0><pre><font color=#%06x>\n", lcolor
    );
  
  for(int y=0; y<srcS->sy; y++) {
    for(int x=0; x<srcS->sx; x++) {
      int ncolor = getCol(srcS->get(x,y)) & 0xFFFFFF;
      char c = getChar(srcS->get(x,y));
      if(c == 0) c = 32;
      if(ncolor != lcolor && c != 32) {
        fprintf(f, mode ? "[/color][color=#%06x]" : "</font><font color=#%06x>", ncolor);
        lcolor = ncolor;
        }
      fprintf(f, "%c", c);
      }
    fprintf(f, "\n");
    }
  fprintf(f, mode ? "[/color][/tt]" : "</font></body></html>\n");

  fclose(f);
  return 0;
  }

int lh_drawScreen(lua_State *L) {
  itl = luaO(1, Image);
  Screen *scr = luaO(2, Screen);
  int ox = luaInt(3); int oy = luaInt(4);
  int tx = luaInt(5); int ty = luaInt(6);
  
  for(int y=0; y<scr->sy; y++)
    for(int x=0; x<scr->sx; x++) {
      drawTile(itl->s, ox+x*tx, oy+y*ty, tx, ty, distill(scr->get(x,y), spFlat));
      }
  
  return 0;
  }

int lh_drawScreenX(lua_State *L) {
  itl = luaO(1, Image);
  Screen *scr = luaO(2, Screen);
  int ox = luaInt(3); int oy = luaInt(4);
  int tx = luaInt(5); int ty = luaInt(6);
  
  for(int y=0; y<scr->sy; y++)
    for(int x=0; x<scr->sx; x++) {

      int& C1(scr->get(x, y));
      lua_pushvalue(L, -1);
      lua_pushinteger(L, C1);
      lua_pushinteger(L, x);
      lua_pushinteger(L, y);
      
      if (lua_pcall(L, 3, 1, 0) != 0) {
        fprintf(errfile, "error running drawScreenX: %s\n", lua_tostring(L, -1));
        halt();
        }
  
      int C2 = luaInt(-1);
      lua_pop(L, 1);
      
      drawTile(itl->s, ox+x*tx, oy+y*ty, tx, ty, distill(C2, spFlat));
      }
  
  return 0;
  }

int lh_drawTile(lua_State *L) {
  itl = luaO(1, Image);
  int ox = luaInt(3); int oy = luaInt(4);
  int tx = luaInt(5); int ty = luaInt(6);

  drawTile(itl->s, ox, oy, tx, ty, distill(luaInt(2), spFlat));
  return 0;
  }
#endif
