/**
 * prefs.c - prefs for SciteProj
 *
 *  Copyright 2006 Roy Wood, 2009-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 <string.h>

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

#include "prefs.h"
#include "string_utils.h"
#include "script.h"
#include "file_utils.h"

/**
 *
 */

gboolean check_for_old_style_config();
int load_lua_config(gchar *filename, gchar *full_string);

/**
 *
 */
sciteproj_prefs prefs;

gchar *prefs_filename;

gchar *default_config_string = (gchar*)"" \
                             "-----------------------------\n"
                             "-- Configuration for SciteProj\n"
                             "-----------------------------\n"
                             "\n"
                             "-- Window geometry:\n"
                             "xpos=40\n"
                             "ypos=40\n"
                             "width=200\n"
                             "height=400\n"
                             "\n"
                             "-- Search window geometry (-1 on xpos and ypos means default center screen):\n"
                             "search_xpos=-1\n"
                             "search_ypos=-1\n"
                             "search_width=500\n"
                             "search_height=400\n"
                             "\n"
                             "search_alert_file_warnings=TRUE\n"
                             "search_match_case=FALSE\n"
                             "search_match_whole_words=FALSE\n"
                             "search_trim_results=TRUE\n"
                             "\n"
                             "-- other:\n"
                             "give_scite_focus=FALSE\n"
                             "search_give_scite_focus=TRUE\n"
                             "\n"
                             "show_recent=FALSE\n"
                             "recent_add_to_bottom=FALSE\n"
                             "\n"
                             "hide_statusbar=FALSE\n"
                             "\n"
                             "\n";

/**
 *		Check config string - is it valid?
 */
gboolean check_config_string(gchar *in_config)
{
   gboolean result = FALSE;
   int co = 0;
   gdouble tempdouble;

   gchar *tempstring = NULL;

   int pos = -1;

   gchar *value = in_config;

   // clear scite Path

   prefs.scite_path = NULL;

   for (co = 0; co < (int)strlen(in_config); co++) {
      if (in_config[co] == '=') pos = co;

      if (pos == -1) {
         value++;
      }
   }

   if (pos != -1) {
      tempstring = g_strndup(in_config, pos);
      value++;
   }

   if ((tempstring != NULL) && (value != NULL)) {

      tempstring = g_strchug(tempstring);
      tempstring = g_strchomp(tempstring);

      value = g_strchug(value);
      value = g_strchomp(value);

      if (g_ascii_strcasecmp(tempstring, "xpos") == 0) {
         tempdouble = g_ascii_strtod(value, NULL);
         prefs.xpos = (int) tempdouble;
      }

      if (g_ascii_strcasecmp(tempstring, "ypos") == 0) {
         tempdouble = g_ascii_strtod(value, NULL);
         prefs.ypos = (int)tempdouble;
      }

      if (g_ascii_strcasecmp(tempstring, "width") == 0) {
         tempdouble = g_ascii_strtod(value, NULL);
         prefs.width = (int)tempdouble;
      }

      if (g_ascii_strcasecmp(tempstring, "height") == 0) {
         tempdouble = g_ascii_strtod(value, NULL);
         prefs.height = (int)tempdouble;
      }

      if (g_ascii_strcasecmp(tempstring, "give_scite_focus") == 0) {
         if (g_ascii_strcasecmp(value, "TRUE") == 0) {
            prefs.give_scite_focus = TRUE;
         }
      }


      if (g_ascii_strcasecmp(tempstring, "scite_path") == 0) {
         prefs.scite_path = g_strdup_printf("%s", value);
      }

      if (g_ascii_strcasecmp(tempstring, "show_recent") == 0) {
         if (g_ascii_strcasecmp(value, "TRUE") == 0) {
            prefs.show_recent = TRUE;
         }
      }

      if (g_ascii_strcasecmp(tempstring, "recent_add_to_bottom") == 0) {
         if (g_ascii_strcasecmp(value, "TRUE") == 0) {
            prefs.recent_add_to_bottom = TRUE;
         }
      }

      if (g_ascii_strcasecmp(tempstring, "hide_statusbar") == 0) {
         if (g_ascii_strcasecmp(value, "TRUE") == 0) {
            prefs.hide_statusbar = TRUE;
         }
      }

      if (g_ascii_strcasecmp(tempstring, "start_scite") == 0) {
         if (g_ascii_strcasecmp(value, "TRUE") == 0) {
            prefs.start_scite = TRUE;
         }
      }
   }

   if (tempstring != NULL) g_free(tempstring);

   return result;
}



/**
 *		init_prefs
 */
gboolean init_prefs(gchar *target_directory, GError **err)
{
   //FILE *fp;
   //gchar buf[PREFS_BUFSIZE];

   gchar *config_string = NULL;

   gboolean result = TRUE;

   // the list of strings
   gchar **list = NULL;

   // Set default values
   prefs.lhs = 1;
   prefs.width = 200;
   prefs.height = 600;
   prefs.verbosity = 0; // No informational messages
   prefs.last_file_filter = -1; // All files (my choice)

   prefs.give_scite_focus = FALSE;

   prefs.show_recent = FALSE;
   prefs.recent_add_to_bottom = FALSE;

   prefs.scite_path = NULL;

   prefs.hide_statusbar = FALSE;

   prefs.start_scite = FALSE;

   prefs.hide_filter_global = NULL;

   // First, check the file ~/.config/sciteprojrc.lua

   gchar *test_prefs_filename = g_build_filename(g_get_user_config_dir(), "sciteprojrc.lua", NULL);

   if (g_file_test(test_prefs_filename, G_FILE_TEST_IS_REGULAR)) {

      // the file exists, load it:

      if (!g_file_get_contents(test_prefs_filename, &config_string, NULL, err)) {
         result = FALSE;
         goto ERROR;
      }

      if (load_lua_config(test_prefs_filename, config_string) != 0) {
         printf("error loading LUA config!\n");
      }

      g_free(config_string);
   }

   g_free(test_prefs_filename);

   // Otherwise, check current directory, and the directories that the previous
   // versions used

   test_prefs_filename = g_build_filename(target_directory, "sciteprojrc.lua", NULL);

   if (!g_file_test(test_prefs_filename, G_FILE_TEST_IS_REGULAR)) {

      // the result of g_get_user_config_dir doesn't need to be freed, so we
      // dont need to put it in a pointer of its own.
      prefs_filename = g_build_filename(g_get_user_config_dir(), "sciteprojrc", NULL);

      // Check if a config-file exists
      if (!g_file_test(prefs_filename, G_FILE_TEST_IS_REGULAR)) {

         // First, check if ~/.sciteproj exists.
         gchar *old_configfilename = g_build_filename(g_get_home_dir(), ".sciteproj", NULL);

         if (!g_file_test(old_configfilename, G_FILE_TEST_IS_REGULAR)) {

            // No config-file exists, default to sciteprojrc.lua
            prefs_filename = g_strdup(test_prefs_filename);
         }
      }

   } else {
      prefs_filename = g_strdup(test_prefs_filename);
   }

   g_free(test_prefs_filename);

   // Load preferences from config

   if (!g_file_get_contents(prefs_filename, &config_string, NULL, err)) {

      result = FALSE;
      goto ERROR;
   }

   // Check if it is an old-style config, or a new LUA one
   if (check_for_old_style_config(config_string)) {

      gchar **savedlist;

      debug_printf("Old style config\n");
      // split out the lines, and add each to the list of strings
      list = g_strsplit(config_string, "\n", -1);

      savedlist = list;

      gchar *temp = NULL;

      do {

         temp = *list;

         if (temp != NULL) {

            if ((temp[0] != '#') && (strcmp(temp, "") != 0)) {
               // We got a valid string:
               // no starting #, and not an empty string.

               check_config_string(temp);
            }
            list++;
         }

      } while (temp != NULL);

      g_strfreev(savedlist);
   } else {
      // ----- New style (LUA) config



      //if (!load_lua_config(config_string)) {
      if (load_lua_config(prefs_filename, config_string) != 0) {
         printf("error loading LUA config!\n");
      }
   }

ERROR:

   g_free(config_string);

   return result;
}

/**
 *
 */
void done_prefs()
{
   g_free(prefs_filename);
}


/**
 *
 */
gboolean check_for_old_style_config(const gchar *teststring)
{
   gboolean result = FALSE;
   int co = 0;

   // We satisfy it by checking for the default header and assume that if
   // that is there, we have an old-styled (non-LUA) config file

   if (g_str_has_prefix(teststring,
                        "# ---------------------------\n"
                        "# Configuration for SciteProj\n"
                        "# ---------------------------\n")
      ) {
      result = TRUE;
   }

   // Another way to check is to check for lines starting with # - as a comment
   // LUA uses "--", so this is should work to identify oldstyle config.

   for (co = 0; co < strlen(teststring); co++) {
      if (teststring[co] == '\n') {
         //printf("Tecken: %c\n", teststring[co+1]);

         if (teststring[co + 1] == '#') {
            result = TRUE;
         }
      }
   }

   return result;
}


/**
 *
 */
int load_lua_config(gchar *filename, gchar *full_string)
{
   lua_State *lua;
   lua = init_script();

   //if (load_script_buffer(lua, config_string)!=0) {
   if (load_script_buffer(lua, full_string) != 0) {
      printf("Error loading file: %s\n", filename);
      return FALSE;
   }

   run_script(lua);

   if (lua_global_exists(lua, "xpos"))
      prefs.xpos = lua_get_number(lua, "xpos");

   if (lua_global_exists(lua, "ypos"))
      prefs.ypos = lua_get_number(lua, "ypos");

   if (lua_global_exists(lua, "width"))
      prefs.width = lua_get_number(lua, "width");

   if (lua_global_exists(lua, "height"))
      prefs.height = lua_get_number(lua, "height");

   if (lua_global_exists(lua, "give_scite_focus"))
      prefs.give_scite_focus = lua_get_boolean(lua, "give_scite_focus");

   if (lua_global_exists(lua, "show_recent"))
      prefs.show_recent = (gboolean)lua_get_boolean(lua, "show_recent");

   if (lua_global_exists(lua, "recent_add_to_bottom"))
      prefs.recent_add_to_bottom = (gboolean)lua_get_boolean(lua, "recent_add_to_bottom");

   if (lua_global_exists(lua, "hide_statusbar"))
      prefs.hide_statusbar = lua_get_boolean(lua, "hide_statusbar");

   if (lua_global_exists(lua, "use_stock_folder_icon"))
      prefs.use_stock_folder_icon = lua_get_boolean(lua, "use_stock_folder_icon");

   if (lua_global_exists(lua, "write_protect"))
      prefs.write_protect = lua_get_boolean(lua, "write_protect");

   if (lua_global_exists(lua, "start_scite"))
      prefs.start_scite = lua_get_boolean(lua, "start_scite");

   if (lua_global_exists(lua, "hide_filter_global")) {

      lua_getglobal(lua, "hide_filter_global");

      if (lua_isnil(lua, -1)) {
         printf("hide_filter_global not available in preferences.\n");
         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
         printf("Expected a table...\n");
         goto EXITPOINT;
      }

      lua_pushnil(lua);

      while(lua_next(lua, -2)) {

         // stack now contains: -1 => value; -2 => key; -3 => table
         // copy the key so that lua_tostring does not modify the original
         lua_pushvalue(lua, -2);
         // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
         const gchar *value = lua_tostring(lua, -2);

         if (value != NULL) {

            gchar *temp_string = g_strdup((gchar*)(value));

            prefs.hide_filter_global = g_slist_append(prefs.hide_filter_global, (gchar*)temp_string);
         }
         // pop value + copy of key, leaving original key
         lua_pop(lua, 2);
         // stack now contains: -1 => key; -2 => table
      }

   }

EXITPOINT:
   if (lua)
      done_script(lua);

   return 0;
}
