/*
 * Copyright (C) 2002,2003,2004 Daniel Heck
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *  
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */
#ifndef LUA_HH
#define LUA_HH

#include "enigma.hh"
#include "ecl_geom.hh"
#include "file.hh"
#include "GridObject.hh"
#include <map>

#ifdef CXXLUA
struct lua_State;
#else 
extern "C" struct lua_State;
#endif


namespace enigma { namespace lua {

/* -------------------- Data structures -------------------- */

    struct CFunction {
        int (*func) (lua_State *); // lua_CFunction func;
        const char *name;
    };
    
    
    typedef std::map<std::string, int (*) (lua_State *)> MethodMap;
    
    enum Error {
        NO_LUAERROR = 0,
        ERRRUN,
        ERRFILE,
        ERRSYNTAX,
        ERRMEM,
        ERRERR
    };

/* -------------------- Lua states for Enigma -------------------- */

    lua_State *GlobalState();
    void ShutdownGlobal();

    /*! Return the Lua state that is active while the game is running.
      This state is used to execute the Lua code that builds the level
      and to execute signal callbacks and event handlers while the
      game is running. */
    lua_State *LevelState();

    /*! Initialize the ingame Lua state. */
    lua_State *InitLevel(int api);

    /*! Close the ingame Lua state. */
    void ShutdownLevel();


/* -------------------- Enigma/Lua bindings -------------------- */

    int FindDataFile (lua_State *L);

/* -------------------- Helper routines -------------------- */

    void RegisterLuaType(lua_State *L, std::string registryKey, CFunction *ops,
        CFunction *methods, MethodMap &methodMap);


    /*! Register the C functions in `funcs'.  The end of the array is
      denoted by an entry with func==0. */
    void RegisterFuncs (lua_State *L, CFunction funcs[]);

    /*! Set the value of entry `name' in the global table `tablename'. */
    void SetTableVar (lua_State *L, const char *tablename, const char *name, double value);

    bool IsFunc(lua_State *L, const char *funcname);
    
    /*! Call a Lua function with one argument.  This is mainly used
      for callbacks during the game. */
    Error CallFunc(lua_State *L, std::string funcpath, const enigma::Value& arg, Object *obj, bool expectFunction = true);
    
    std::string NewMessageName(lua_State *L, const Object *obj, const std::string &message);
    
    void SetDefaultFloor(lua_State *L, int x, int y);

    /**
     * Run a Lua script using a given absolute path.
     */
    Error DoAbsoluteFile (lua_State *L, const std::string & filename);

    /*! Find a Lua script using enigma::FindFile and run it. */
    Error Dofile (lua_State *L, const std::string & filename);

    /*! Find a system Lua script using enigma::FindFile and run it. */
    Error DoSysFile (lua_State *L, const std::string & filename);

    /*! Find a Lua script in given filesystem using enigma::FindFile and run it. */
    Error DoGeneralFile(lua_State *L, GameFS * fs, const std::string &filename);

    /*! Run the Lua code contained in `luacode'. */
    Error Dobuffer (lua_State *L, const ByteVec &luacode);

    /*! Try to run given file on given filesystem.  If something
      fails, provide generic error message and exit enigma.*/
    void CheckedDoFile (lua_State *L, GameFS * fs, const std::string &filename);

    /*! Return the text of the last error message. */
    std::string LastError(lua_State *L);


    Error DoSubfolderfile(lua_State *L, 
                        const std::string & basefolder, 
                        const std::string & filename);

}} // namespace enigma::lua
#endif

