/**
 * $Id: sgad.cpp 163065 2015-03-27 18:41:34Z fpina $
 * "startup" do SGA daemon
 */

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

extern "C" {
  #include <lua.h>
  #include <lualib.h>
  #include <lauxlib.h>
  #include <compat-5.2.h>
  #include <luacompat52.h>
  #include <luasocket.h>
  #include <luastruct.h>
  #include <luatuple.h>
  #include <loop.h>
  #include <luacothread.h>
  #include <luaidl.h>
  #include <oil.h>
  #include <luasec.h>
  #include "sgalua.h"
}

#include "sgalib.h"
#include "sgautils.h"

/**
 * Função principal do SGA.
 */
int main( int argc, char *argv[] )
{
  int debugmode = 0;
  if (argc > 1) {
    if (argc==2 && strcmp("debug", argv[1])==0 ) {
      debugmode = 1;
    } else {
      fprintf(stderr, "Argumentos invalidos.\n");
      return 1;
    }
  }

  // luaL_reg *ptr;

  // Inicialização de Lua
  lua_State *L = lua_open();

  // Carrega as bibliotecas padrão de Lua
  luaL_openlibs(L);

  /* preload binded C libraries */
  #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM > 501
    luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
  #else
    luaL_findtable(L, LUA_GLOBALSINDEX, "package.preload", 1);
  #endif

  lua_pushcfunction(L,luaopen_struct);lua_setfield(L,-2,"struct");
  lua_pushcfunction(L,luaopen_socket_core);lua_setfield(L,-2,"socket.core");
  lua_pop(L, 1);  /* pop 'package.preload' table */

  luapreload_luacompat52(L);
  luapreload_luasec(L);
  luapreload_luatuple(L);
  luapreload_loop(L);
  luapreload_luacothread(L);
  luapreload_luaidl(L);
  luapreload_oil(L);
  luapreload_sgalua(L);

  if (debugmode == 1) {
    int top = lua_gettop(L);
    int status = luaL_dostring(L,
     "table.insert(package.loaders, (table.remove(package.loaders, 1)))");
    if (status != 0) {
      const char *msg = lua_tostring(L, -1);
      if (msg == NULL) msg = "(error object is not a string)";
      fprintf(stderr, "Erro na ativacao do modo debug: %s.", msg);
    }
    lua_settop(L, top);
  }

  luaL_requiref(L, "sga", luaopen_sga, 1);
  sga_require(L, "main");

  // Encerramento do programa
  lua_close(L);

  return 0;
}

/**
 * Função principal definida para o Windows.
 *
 * Invoca a função main.
 *
 */
#ifdef WIN32
#include <windows.h>
int PASCAL WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int ncmdshow) {
  int rc;
  extern int __argc;
  extern char** __argv;
  rc = main(__argc, __argv);
  return (int) rc;
}
#endif
