/*!
  \file
  \brief Lua の補助

  \author Satofumi KAMIMURA

  $Id: LuaHandler.cpp 1816 2010-05-08 06:11:41Z satofumi $
*/

#include "LuaHandler.h"
#include "fileExist.h"
#include "log_printf.h"
#include <sstream>
#include <string>

using namespace qrk;
using namespace std;


namespace
{
    void handleError(lua_State* L)
    {
        string error_message = lua_tostring(L, -1);

        log_printf("error: %s\n", error_message.c_str());
    }
}


struct LuaHandler::pImpl
{
    string error_message_;
    lua_State* L_;
    string path_;


    pImpl(void) : error_message_("Not initialized."), L_(lua_open()), path_("")
    {
        luaL_openlibs(L_);
    }


    ~pImpl(void)
    {
        // exit() 時に lua に登録したオブジェクトが生成順に関係なく削除され、
        // Segmentation falt が起きるため、閉じないことにする
        // lua_close(L_);
    }


    static pImpl* object(void)
    {
        static pImpl singleton_object;
        return &singleton_object;
    }
};


LuaHandler::LuaHandler(void) : pimpl(pImpl::object())
{
}


LuaHandler::~LuaHandler(void)
{
}


lua_State* LuaHandler::pointer(void)
{
    return pImpl::object()->L_;
}


lua_State* LuaHandler::newthread(lua_State* L)
{
    return lua_newthread(L);
}


void LuaHandler::addPath(lua_State* L, const char* additional_path)
{
    LuaHandler lua_handler;
    lua_handler.pimpl->path_ += string(additional_path) + ";";

    // パス設定の評価
    string lua_path = "package.path = \"" + lua_handler.pimpl->path_ + "\"";
    lua_handler.dostring(L, lua_path.c_str());
}


int LuaHandler::dofile(lua_State* L, const char* lua_file)
{
    int ret = luaL_dofile(L, lua_file);
    if (ret) {
        handleError(L);
    }
    return ret;
}


int LuaHandler::dofile_noext(lua_State* L, const char* lua_file)
{
    const char *ext[] = { ".out", ".lua" };
    size_t n = sizeof(ext) / sizeof(ext[0]);
    for (size_t i = 0; i < n; ++i) {
        string file = string(lua_file) + ext[i];
        if (fileExist(file.c_str())) {
            int ret = dofile(L, file.c_str());
            if (ret) {
                handleError(L);
            }
            return ret;
        }
    }
    return dofile(L, lua_file);
}


int LuaHandler::dostring(lua_State* L, const char* lua_string)
{
    int ret = luaL_dostring(L, lua_string);
    if (ret) {
        handleError(L);
    }
    return ret;
}


void LuaHandler::registerValue(lua_State* L, const char* name, int value)
{
    lua_pushnumber(L, value);
    lua_setglobal(L, name);
}
