// Necklace of the Eye v3.0
// roguelike frontend
// Copyright (C) 2010-2011 Zeno Rogue, see 'noteye.h' for details

static vector<Object*> objs;
static const char *lastfn;
static void halt();

// critical errors
static FILE *errfile;

// log file
static FILE *logfile;

Object* noteye_getobj(int id) {
  if(id <= 0 || id > (int) objs.size()) {
    fprintf(errfile, "No such object (%s)\n", lastfn);
    noteye_halt();
    }
  return objs[id];
  }
  
Object* noteye_getobjd(int id) {
  if(id <= 0 || id > (int) objs.size()) return NULL;
  return objs[id];
  }

void noteye_wrongclass(int id) {
  fprintf(errfile, "Object #%d is of wrong class (%s)\n", id, lastfn);
  halt();
  }

void deleteobj(int idx) {
  delete objs[idx];
  objs[idx] = NULL;
  }

static int ZZ;

int& qpixel(SDL_Surface *surf, int x, int y) {
  if(x<0 || y<0 || x >= surf->w || y >= surf->h) return ZZ;
  char *p = (char*) surf->pixels;
  p += y * surf->pitch;
  int *pi = (int*) (p);
  return pi[x];
  }

uint8& part(int& col, int i) {
  uint8* c = (uint8*) &col;
  return c[i];
  }
  
void recolor(int& col, int ncol, int mode) {

  if(mode == recMult) {
    for(int p=0; p<4; p++)
      part(col, p) = (part(col, p) * part(ncol, p) + 127) / 255;
    return;
    }

  if(mode == recPurple)
    if(!(part(col,0) == part(col,2) && part(col,0) > part(col,1)))
      return;

  uint8 cmax = 0, cmin = 255;
  for(int p=0; p<3; p++)
    cmax = max(cmax, part(col,p)), 
    cmin = min(cmin, part(col,p));
  for(int p=0; p<3; p++)
    part(col,p) = cmin + ((1+cmax-cmin) * part(ncol, p))/ 256;
  }

void mixcolor(int& col, int ncol) {
  col = ((col&0xFEFEFE) + (ncol&0xFEFEFE)) >> 1;
  }

uint8 mixpart(uint8 a, uint8 b, uint8 c) {
  return (a*(255-c)+b*c+127)/255;
  }

bool istrans(int a, int b) { return (a&0xFFFFFF) == (b&0xFFFFFF); }

void mixcolorAt(int& col, int ncol, int p) {
  for(int i=0; i<3; i++)
    part(col,i) = mixpart(part(col,i), part(col,i), part(p, i));
  }

typedef unsigned char uint8;

void alphablend(int& col, int ncol) {
  for(int i=0; i<3; i++) {
    int s3 = part(ncol, 3);
    part(col, i) = 
      (part(col, i) * (255-s3) + part(ncol, i) * s3 + 128) >> 8;
    }
  }

template<class T> int size(T& x) { return x.size(); }

SDL_Surface* newImage(int x, int y) {
  SDL_Surface *surf = SDL_CreateRGBSurface(SDL_HWSURFACE, x, y, 32, 0,0,0,0);
  if(!surf) {
    fprintf(errfile, "Failed to create an image.\n");
    halt();
    }
  return surf;
  }

int sti(string s) { return atoi(s.c_str()); }
int sth(string s) { int ret; sscanf(s.c_str(), "%x", &ret); return ret; }

int tty_fix();

int vgacol[16] = {
  0x0000000, 0x10000aa, 0x200aa00, 0x300aaaa, 0x4aa0000, 0x5aa00aa, 0x6aa5500, 0x7aaaaaa,
  0x8555555, 0x95555ff, 0xA55ff55, 0xB55ffff, 0xCff5555, 0xDff55ff, 0xEffff55, 0xFffffff
  };

#define Get(T, name, id) \
  T* name = dbyId<T> (id)

int registerObject(Object *o) {
  int res = objs.size();
  objs.push_back(o);
  return o->id = res;
  }

#ifdef USELUA
// lua utils

int retInt(lua_State *L, int i) {
  lua_pushinteger(L, i);
  return 1;
  }

int retBool(lua_State *L, bool b) {
  lua_pushboolean(L, b);
  return 1;
  }

int retStr(lua_State *L, string s) {
  lua_pushstring(L, s.c_str());
  return 1;
  }

int retStr(lua_State *L, char *s) {
  lua_pushstring(L, s);
  return 1;
  }

int retObject(lua_State *L, Object *o) {
  return retInt(L, registerObject(o));
  }

void checkArg(lua_State *L, int q, const char *fname) {
  lastfn = fname;
  if(lua_gettop(L) != q) {
    fprintf(errfile, "Bad number of arguments to %s\n", fname);
    halt();
    }
  }

void setfield (lua_State *L, const char *index, int value) {
  lua_pushstring(L, index);
  lua_pushinteger(L, value);
  lua_settable(L, -3);
}

void setfieldStr (lua_State *L, const char *index, const char *str) {
  lua_pushstring(L, index);
  lua_pushstring(L, str);
  lua_settable(L, -3);
}

void setfieldBool (lua_State *L, const char *index, bool b) {
  lua_pushstring(L, index);
  lua_pushboolean(L, b);
  lua_settable(L, -3);
}

void noteye_lua_newtable(lua_State *L) { lua_newtable(L); }

int getfield (lua_State *L, const char *key) {
  int result;
  lua_pushstring(L, key);
  lua_gettable(L, -2);
  result = luaInt(-1);
  lua_pop(L, 1);
  return result;
  }

int noteye_int(lua_State *L, int x) {
  return (int) luaL_checkint(L, x);
  }

long double noteye_num(lua_State *L, int x) {
  return luaL_checknumber(L, x);
  }

bool noteye_bool(lua_State *L, int x) {
  return (bool) lua_toboolean(L, x);
  }

const char *noteye_str(lua_State *L, int x) {
  return luaL_checkstring(L, x);
  }

#endif

