/* ====================================================================
 * FTD4Linux Software License, Version 1.0
 *
 * Copyright (c) 2000-2004 The FTD4Linux Development Team.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        FTD4Linux Development Team (http://www.ftd4linux.2y.net/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "FTD" and "FTD4Linux" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact alguno@ftd4linux.2y.net.
 *
 * 5. Products derived from this software may not be called "FTD4Linux",
 *    nor may "FTD4Linux" appear in their name, without prior written
 *    permission of the FTD4Linux Development Team.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE FTD4LINUX DEVELOPMENT TEAM OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <gmodule.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#endif
#include "ftd_gui_config.h"
#include "ftd_gui_errhandler.h"
#include "ftd_gui_compat_macros.h"

static gboolean gui_enabled;
static gboolean show_html_renderers;

FtdGuiConfig *
ftd_gui_config_new(GtkWidget *parent_window, gboolean enable_gui, gboolean enable_html_renderers)
{
    GtkWidget *cancelbutton1;
    GtkWidget *okbutton1;
    GtkWidget *dialog_vbox1;
    GtkWidget *label;
    FtdGuiConfig *config;

    gui_enabled = enable_gui;
    show_html_renderers = enable_html_renderers;

    config = g_malloc0(sizeof(FtdGuiConfig));

    config->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (config->window), "Configuratie");
    gtk_window_set_position (GTK_WINDOW (config->window), GTK_WIN_POS_CENTER_ALWAYS);
    gtk_window_set_modal(GTK_WINDOW(config->window), TRUE);

    if (parent_window) {
        gtk_window_set_transient_for(GTK_WINDOW(config->window), GTK_WINDOW(parent_window));
    }

    gtk_window_set_resizable (GTK_WINDOW(config->window), FALSE);
    g_signal_connect(G_OBJECT(config->window), "destroy",
                     G_CALLBACK(ftd_gui_config_callback_destroy), config);

    dialog_vbox1 = gtk_vbox_new(FALSE, 0);
    gtk_widget_show (dialog_vbox1);
    gtk_container_add(GTK_CONTAINER(config->window), dialog_vbox1);

    config->notebook = gtk_notebook_new ();
    gtk_widget_show (config->notebook);
    gtk_box_pack_start (GTK_BOX (dialog_vbox1), config->notebook, TRUE, TRUE, 0);

    ftd_gui_config_user_new(config);
    if (enable_gui) {
        ftd_gui_config_settings_new(config, enable_html_renderers);
    }

#ifndef BUILTIN_PLUGIN
    ftd_gui_config_plugin_new(config);
#endif

    if (enable_gui) {
        ftd_gui_config_badwords_new(config);
        ftd_gui_config_groupfilter_new(config);
        ftd_gui_config_catfilters_new(config);
        ftd_gui_config_irc_new(config);
    }

    label = gtk_label_new ("Algemeen");
    gtk_widget_show (label);
    gtk_notebook_append_page(GTK_NOTEBOOK(config->notebook), config->user->widget, label);

    if (enable_gui) {
        label = gtk_label_new ("Instellingen");
        gtk_widget_show (label);
        gtk_notebook_append_page(GTK_NOTEBOOK(config->notebook), config->settings->widget, label);
    }

#ifndef BUILTIN_PLUGIN
    label = gtk_label_new ("Plugins");
    gtk_widget_show (label);
    gtk_notebook_append_page(GTK_NOTEBOOK(config->notebook), config->plugin->widget, label);
#endif

    if (enable_gui) {
        label = gtk_label_new("Bad words");
        gtk_widget_show (label);
        gtk_notebook_append_page(GTK_NOTEBOOK(config->notebook), config->badwords->widget, label);

        if (ftd_config_get()->groupFilter) {
            label = gtk_label_new("Groepsfilter");
            gtk_widget_show(label);
            gtk_notebook_append_page(GTK_NOTEBOOK(config->notebook), config->groupfilter->widget, label);
        }

        label = gtk_label_new("Categoriefilters");
        gtk_widget_show (label);
        gtk_notebook_append_page(GTK_NOTEBOOK(config->notebook), config->catfilters->widget, label);

        label = gtk_label_new("IRC Chat");
        gtk_widget_show (label);
        gtk_notebook_append_page(GTK_NOTEBOOK(config->notebook), config->irc->widget, label);
    }

    cancelbutton1 = gtk_button_new_from_stock ("gtk-cancel");
    gtk_widget_show (cancelbutton1);

    okbutton1 = gtk_button_new_from_stock ("gtk-ok");
    gtk_widget_show (okbutton1);

    gtk_container_add(GTK_CONTAINER(dialog_vbox1), okbutton1);
    gtk_container_add(GTK_CONTAINER(dialog_vbox1), cancelbutton1);

    gtk_widget_show(config->window);

    g_signal_connect((gpointer) cancelbutton1, "clicked",
                     G_CALLBACK(ftd_gui_config_callback_cancel), config);
    g_signal_connect((gpointer) okbutton1, "clicked",
                     G_CALLBACK(ftd_gui_config_callback_ok), config);

    return config;
}

void
ftd_gui_config_free(FtdGuiConfig *config)
{
    g_assert(config);

    ftd_gui_config_user_free(config);
    if (gui_enabled) {
        ftd_gui_config_settings_free(config);
    }
#ifndef BUILTIN_PLUGIN
    ftd_gui_config_plugin_free(config);
#endif
    if (gui_enabled) {
        ftd_gui_config_badwords_free(config);
        if (config->groupfilter) {
            ftd_gui_config_groupfilter_free(config);
        }
        ftd_gui_config_catfilters_free(config);
        ftd_gui_config_irc_free(config);
    }
    //gtk_widget_destroy(config->window);
    g_free(config);
}

gboolean
ftd_gui_config_callback_destroy(GtkWidget *caller, gpointer data)
{
    char *errmsg;

    ftd_gui_config_free( (FtdGuiConfig*)data );

    if (ftd_config_get()->firstTime) {
        /* We bevinden ons nog in de first time modus..roep gtk_main_quit aan om
           terug te gaan naar main() waarvanuit we het normale programma kunnen opstarten */
        gtk_main_quit();

        return FALSE;
    }

    if (!gui_enabled) {
        gtk_main_quit();

        return FALSE;
    }

    // Moet nog netter kunnen
    if (!ftd_group_list_ready()) {
        ftd_group_fetch(&errmsg);
    }

    return FALSE;
}

gboolean
ftd_gui_config_callback_cancel(GtkWidget *caller, gpointer data)
{
    gtk_widget_destroy(((FtdGuiConfig *) data)->window);

    return FALSE;
}

gboolean
ftd_gui_config_callback_ok(GtkWidget *caller, gpointer data)
{
    FtdGuiConfig *config = (FtdGuiConfig *) data;

    g_assert(config);

    /* Controleer of er een geldige waarde voor de username en password is ingevuld */
    if (strlen(gtk_entry_get_text(GTK_ENTRY(config->user->username))) <= 0) {
        GtkWidget *dialog;
        dialog = gtk_message_dialog_new (GTK_WINDOW (config->window),
                                  GTK_DIALOG_DESTROY_WITH_PARENT,
                                  GTK_MESSAGE_ERROR,
                                  GTK_BUTTONS_CLOSE,
                                  "Je bent vergeten om de username in te vullen\n"
                                  "Deze is vereist om dit programma te gebruiken");
        gtk_dialog_run (GTK_DIALOG (dialog));
        gtk_widget_destroy (dialog);
        gtk_widget_grab_focus (config->user->username);
        return FALSE;
    }

    if (strlen(gtk_entry_get_text(GTK_ENTRY(config->user->password))) <= 0) {
        GtkWidget *dialog;
        dialog = gtk_message_dialog_new (GTK_WINDOW (config->window),
                                  GTK_DIALOG_DESTROY_WITH_PARENT,
                                  GTK_MESSAGE_ERROR,
                                  GTK_BUTTONS_CLOSE,
                                  "Je bent vergeten om het password in te vullen\n"
                                  "Deze is vereist om dit programma te gebruiken");
        gtk_dialog_run (GTK_DIALOG (dialog));
        gtk_widget_destroy (dialog);
        gtk_widget_grab_focus (config->user->password);
        return FALSE;
    }

    if (atoi(gtk_entry_get_text (GTK_ENTRY(config->user->proxyPort))) > 65535) {
        GtkWidget *dialog;
        dialog = gtk_message_dialog_new (GTK_WINDOW (config->window),
                                  GTK_DIALOG_DESTROY_WITH_PARENT,
                                  GTK_MESSAGE_ERROR,
                                  GTK_BUTTONS_CLOSE,
                                  "Je hebt een ongeldig poortnummer ingevuld voor de proxy\n"
                                  "Dit moet een waarde tussen de 1 en 65535 zijn\n"
                                  "Deze is vereist om dit programma te gebruiken");
        gtk_dialog_run (GTK_DIALOG (dialog));
        gtk_widget_destroy (dialog);
        gtk_widget_grab_focus (config->user->proxyPort);
        return FALSE;
    }

    if (ftd_config_get()->username) {
        ftd_string_free (ftd_config_get()->username);
    }
    if (ftd_config_get()->password) {
        ftd_string_free (ftd_config_get()->password);
    }
    if (ftd_config_get()->proxyHost) {
        ftd_string_free (ftd_config_get()->proxyHost);
    }
    if (ftd_config_get()->proxyPort) {
        ftd_string_free (ftd_config_get()->proxyPort);
    }
    if (ftd_config_get()->proxyUser) {
        ftd_string_free (ftd_config_get()->proxyUser);
    }
    if (ftd_config_get()->proxyPassword) {
        ftd_string_free (ftd_config_get()->proxyPassword);
    }

    /* user */
    ftd_config_get()->username = strlen(gtk_entry_get_text(GTK_ENTRY(config->user->username))) > 0 ?
                                ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->user->username))) : NULL;
    ftd_config_get()->password = strlen(gtk_entry_get_text(GTK_ENTRY(config->user->password))) > 0 ?
                                ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->user->password))) : NULL;
    ftd_config_get()->proxyHost = strlen(gtk_entry_get_text(GTK_ENTRY(config->user->proxyHost))) > 0 ?
                                ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->user->proxyHost))) : NULL;
    ftd_config_get()->proxyPort = strlen(gtk_entry_get_text(GTK_ENTRY(config->user->proxyPort))) > 0 ?
                                ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->user->proxyPort))) : NULL;
    ftd_config_get()->proxyUser = strlen(gtk_entry_get_text(GTK_ENTRY(config->user->proxyUser))) > 0 ?
                                ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->user->proxyUser))) : NULL;
    ftd_config_get()->proxyPassword = strlen(gtk_entry_get_text(GTK_ENTRY(config->user->proxyPass))) > 0 ?
                                ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->user->proxyPass))) : NULL;

    ftd_config_get()->verwijderPostsNaXDagen = gtk_combo_box_get_active(GTK_COMBO_BOX(config->user->comboVerwijderPostsNaXDagen));

    ftd_config_get()->ratingScale = gtk_range_get_value(GTK_RANGE(config->user->ratingScale));

    /* settings */
    if (gui_enabled) {
        char *text;

        ftd_config_get()->toonInfoBijEenZoekresultaat = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->toonInfoBijEenZoekresultaat));
        ftd_config_get()->updatenBijOpstarten = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->updatenBijOpstarten));
        ftd_config_get()->startMaximized = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->startMaximized));
        ftd_config_get()->toonStatusBijLaden = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->toonStatusBijLaden));
        ftd_config_get()->toonCategoriseerdeLijstBijKnopNieuw = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->toonCategoriseerdeLijstBijKnopNieuw));
#ifndef DARWIN
        ftd_config_get()->trayIcon = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->trayIcon));
#endif
        ftd_config_get()->toonGUIGroupFilter = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->toonGUIGroupFilter));
        ftd_config_get()->groupFilter = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->groupFilter));
        ftd_config_get()->recursiveUpdate = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->recursiveUpdate));
        ftd_config_get()->geenTabbedBrowsing = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->geenTabbedBrowsing));
        ftd_config_get()->toonWatcherNotifications = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->toonWatcherNotifications));
        ftd_config_get()->openPostinfoOpAchtergrond = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->openPostinfoOpAchtergrond));

        if (show_html_renderers) {
            ftd_config_get()->gebruikFontFamily = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->settings->gebruikFontFamily));


            if (ftd_config_get()->htmlRenderer) {
                ftd_string_free(ftd_config_get()->htmlRenderer);
            }

            text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(config->settings->htmlRenderer));
            if (strcmp(text, "Geen bruikbare HTML renderers gevonden!") == 0) {
                ftd_config_get()->htmlRenderer = ftd_string_new("");
            } else {
                ftd_config_get()->htmlRenderer = ftd_string_new(text);
            }
            g_free(text);
        }

        /* Groupfilter */
        if (ftd_config_get()->groupFilterList) {
            ftd_splitted_list_free(&ftd_config_get()->groupFilterList);
        }

        if (!ftd_config_get()->groupFilter) {
            ftd_config_get()->groupFilterList = NULL;
        } else {
            ftd_config_get()->groupFilterList = ftd_gui_config_groupfilter_get_list(config);
        }

        /* catfilters */
        if (config->catfilters->changed_anything) {
            FTDFilterlist *filterlist = ftd_filterlist_get();
            ftd_filterlist_set_filters(filterlist, config->catfilters->filters);
            g_object_unref(filterlist);
        }

        /* irc */
        ftd_config_get()->toonIRCClient = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->irc->checkEnableIRCClient));

        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config->irc->checkUsernameAsNickname))) {
            if (ftd_config_get()->ircNickname) {
                ftd_string_free(ftd_config_get()->ircNickname);
                ftd_config_get()->ircNickname = NULL;
            }
        } else {
            if (ftd_config_get()->ircNickname) {
                ftd_string_free(ftd_config_get()->ircNickname);
            }

            ftd_config_get()->ircNickname = ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->irc->entryNickname)));
        }

        if (ftd_config_get()->ircAltNickname) {
            ftd_string_free(ftd_config_get()->ircAltNickname);
        }

        ftd_config_get()->ircAltNickname = ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->irc->entryAltNickname)));
    }

    /* plugins */
#ifndef WIN32
#ifndef BUILTIN_PLUGIN
    ftd_config_get()->authPlugin = strlen(gtk_entry_get_text(GTK_ENTRY(config->plugin->authLocation))) > 0 ?
                                ftd_string_new(gtk_entry_get_text(GTK_ENTRY(config->plugin->authLocation))) : NULL;
#endif
#endif

    if (ftd_config_get()->firstTime == TRUE) {
        ftd_config_get()->firstTime = FALSE;
        gtk_main_quit();
    }

    ftd_config_save();

    gtk_widget_destroy(config->window);

    return FALSE;
}

FtdList *
ftd_gui_config_get_html_renderers(void)
{
    FtdList *ret = NULL;
    char *directory = ftd_file_parse_lib_dir("/openftd");
    GDir *dir;
    const char *filename;
    const char *(*get_name_func) (void);
    GError *err = NULL;

    dir = g_dir_open(directory, 0, &err);

    if (!dir) {
        char *msg = g_strdup_printf("Fatale fout:\nMap '%s' kan niet gelezen worden. Is de OpenFTD installatie wel compleet?\n\n%s", directory, err->message);
        g_error_free(err);
        ftd_gui_dialog_show(NULL, msg, NULL, TRUE);
        g_free(msg);
        g_free(directory);
        exit(1);
        return NULL;
    }

#ifdef WIN32
    SetErrorMode(SEM_FAILCRITICALERRORS);
#endif

    while ((filename = g_dir_read_name(dir))) {
        char *full_filename = g_build_filename(directory, filename, NULL);
        GModule *plugin = g_module_open(full_filename, G_MODULE_BIND_LOCAL);

        if (!plugin) {
#ifndef WIN32	// Onder Win32 hebben we schijt aan dergelijke foutmeldingen
            g_warning("Error while trying to load '%s': %s\n", full_filename, g_module_error());
#endif
            g_free(full_filename);
            continue;
        }

        if (g_module_symbol(plugin, "ftd_gui_browser_get_name", (gpointer *) &get_name_func)) {
            const char *plugin_name = get_name_func();

            if (plugin_name == NULL) {
                g_print("plugin_name == NULL bij filename '%s'\n", full_filename);
            } else {
                // Controleer of we deze plugin niet eerder zijn voorbij gekomen
                FtdGuiConfigHTMLRenderer *item;
                FtdList *list_tmp = ret;
                gboolean found = FALSE;

                while (list_tmp) {
                    item = ftd_list_value(list_tmp);

                    if (strcmp(plugin_name, item->name) == 0 && strlen(plugin_name) == strlen(item->name)) {
                        // We hebben een match, sla dit element over
                        found = TRUE;
                        break;
                    }

                    list_tmp = ftd_list_next(list_tmp);
                }

                if (found) {
                    g_module_close(plugin);
                    g_free(full_filename);
                    continue;
                }

                item = g_malloc0(sizeof(FtdGuiConfigHTMLRenderer));

                item->name = g_strdup(plugin_name);
                item->filename = g_strdup(full_filename);

                ret = ftd_list_append(ret, item);
            }
        }

        g_module_close(plugin);

        g_free(full_filename);
    }
#ifdef WIN32
    SetErrorMode(0);
#endif

    g_dir_close(dir);

    if (ret == NULL) {
        char *msg = g_strdup_printf("Fatale fout:\nGeen bruikbare HTML renderers gevonden in '%s'", directory);
        ftd_gui_dialog_show(NULL, msg, NULL, TRUE);
        g_free(msg);
        g_free(directory);
        exit(1);
    }

    g_free(directory);

    return ret;
}

void
ftd_gui_config_free_html_renderers(FtdList *full_list)
{
    FtdList *list = full_list;

    while (list) {
        FtdGuiConfigHTMLRenderer *item = ftd_list_value(list);

        g_free((gpointer) item->name);
        g_free((gpointer) item->filename);
        g_free(item);

        list = ftd_list_next(list);
    }

    ftd_list_free(full_list);
}
