/**
 * script.c - Script code for sciteproj
 *
 *  Copyright 2012-2020 Andreas Rönnquist
 *
 * This file is part of SciteProj.
 *
 * SciteProj 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 3 of the License, or
 * (at your option) any later version.
 *
 * SciteProj 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 SciteProj.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <gtk/gtk.h>

#include <glib.h>
#include <glib/gi18n.h>

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#include <locale.h>

#include "prefs.h"

#include "script.h"

#include "tree_manipulation.h"

/**
 *
 */
lua_State *
init_script()
{
   lua_State *lua = luaL_newstate();
   if (!lua) {
      printf("ERROR!\n");
      return NULL;
   }

   luaL_openlibs(lua);

   register_cfunctions(lua);

   return lua;
}


/**
 *
 */
void
register_cfunctions(lua_State *lua)
{

}


/**
 *
 */
int
load_script(lua_State *lua, char *filename)
{
   if (lua) {
      int result = luaL_loadfile(lua, filename);

      if (result) {
         // We got an error, print it
         printf("%s\n", lua_tostring(lua, -1));

         lua_pop(lua, 1);

         return -1;
      }
   } else {
      return -1;
   }

   return 0;
}


/**
 *
 */
int load_script_buffer(lua_State *lua, const char *buffer)
{
   if (lua) {
      int err = luaL_loadbuffer(lua, buffer, strlen(buffer), "script_buffer");
      if (err) {
         //printf("\n\n\nERROR!\n\n\n");
         fprintf(stderr, "%s\n", lua_tostring(lua, -1));
         lua_pop(lua, -1);
         return -1;
      }

   } else {
      printf("invalid lua state...\n");
      return -1;
   }

   return 0;
}


/**
 *
 */
void run_script(lua_State *lua)
{
   int s = lua_pcall( lua, 0, LUA_MULTRET, 0 );

   if (s > 0) {

      char *error_msg;

      error_msg = (char*)lua_tostring( lua, -1 );

      //std::string luaErrorString=getLuaErrorString(s);

      /*
      mssOut.str( "" );
      mssOut << "Script::runScript : Error caught running script "
         << sScriptName << "\n"
         << "    Error code is " << luaErrorString << ".\n"
         << "    Error msg is: " << errorMsg;
      throw( ScriptException( mssOut.str().c_str(), errorMsg ) );
      */

      printf(_("Error: %s"), error_msg);
      printf("\n");
   }

}


/**
 *
 */
void
done_script(lua_State *lua)
{
   if (lua)
      lua_close(lua);
}


/**
 *
 */
GSList *load_filter_from_lua()
{
   gchar *script_filename = g_build_filename(get_project_directory(), "sciteprojrc.lua", NULL);
   lua_State *lua = NULL;
   GSList *list = NULL;

   if (g_file_test(script_filename, G_FILE_TEST_EXISTS)) {

      lua = init_script();

      if (load_script(lua, script_filename) != 0) {
         printf("Error loading script: %s\n", script_filename);
         goto EXITPOINT;
      }

      run_script(lua);

      lua_getglobal(lua, "hide_filter");

      // Make sure we got a value at all
      if (lua_isnil(lua, -1)) {
         goto EXITPOINT;
      }

      //	Make sure it is a table
      if (!lua_istable(lua, -1)) {
         // We didn't find a table with the required name, then just exit
         goto EXITPOINT;
      }

      lua_pushnil(lua);

      while(lua_next(lua, -2)) {
         if (lua_isstring(lua, -1)) {
            char *temp = (char *)lua_tostring(lua, -1);

            list = g_slist_append(list, g_strdup(temp));
         }
         lua_pop(lua, 1);
      }
      lua_pop(lua, 1);
   }

   // TODO: Also check in user config in ~/.config/sciteprojrc for
   // any settings for current folder

EXITPOINT:
   g_free(script_filename);

   if (lua)
      done_script(lua);

   return list;
}


/**
 *
 */
int lua_get_boolean(lua_State *lua, char *variable_name)
{
   lua_getglobal(lua, variable_name);

   int temp = 0;
   gboolean result = FALSE;

   //if (lua_type(lua,-1)==LUA_TBOOLEAN) {
   if (lua_isboolean(lua, -1)!=0) {
      temp = (int)lua_toboolean(lua, -1);
   } else {
      printf("%s isn't a bool!\n", variable_name);
   }

   lua_pop(lua, 1);

   if (temp != 0) result = TRUE;

   return result;
}


/**
 *
 */
double lua_get_number(lua_State *lua, char *variable_name)
{
   int result = -1;

   lua_getglobal(lua, variable_name);

   if (lua_isnumber(lua, -1) != 0) {
      result = (int)lua_tonumber(lua, -1);
   } else {
      printf("%s isn't a number!\n", variable_name);
   }

   lua_pop(lua, 1);

   return result;
}


/**
 *
 */
int error(lua_State *L, const char *fmt, ...)
{
   va_list argp;
   va_start(argp, fmt);
   vfprintf(stderr, fmt, argp);
   va_end(argp);

   lua_close(L);

   return 0;
}


/**
 *
 */
gboolean lua_global_exists(lua_State *lua, char *variable_name)
{
   gboolean result = TRUE;

   lua_getglobal(lua, variable_name);

   if (lua_isnil(lua, -1) != 0) {
      result = FALSE;
   } else {
      lua_pop(lua, 1);
   }

   return result;
}
