/* ====================================================================
 * 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 <stdio.h>
#include "ftd_gui_main.h"
#include "ftd_gui_categories.h"
#include "ftd_gui_center_eventlist.h"
#include "ftd_gui_worksheet.h"
#include "ftd_gui_sidebar.h"
#include "ftd_gui_categories.h"
#include "ftd_gui_center.h"
#include "ftd_gui_xslt.h"
#include "ftd_gui_config.h"
#include "ftd_gui_parse.h"
#include "ftd_gui_status_filter.h"

static gboolean ftd_gui_categories_rmb_click (GtkWidget *caller, GdkEventButton *event, gpointer data);

void
ftd_gui_categories_new(void)
{
    GtkCellRenderer     *cellRenderer;
    GtkTreeViewColumn   *treeViewColumn;
    GtkTreeSelection    *select;

    FtdGuiCategories *categories = (FtdGuiCategories *) g_malloc(sizeof(FtdGuiCategories));

    g_assert(gui);
    g_assert(gui->worksheet);
    g_assert(gui->worksheet->sidebar);
    gui->worksheet->sidebar->categories = categories;

    categories->widget = gtk_scrolled_window_new (NULL, NULL);

    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (categories->widget),
                                    GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (categories->widget),
                                         GTK_SHADOW_IN);

    /* Create a model */
    categories->treestore = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);

    /* Insert model into the TreeView */
    categories->tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL(categories->treestore));

    /* setup tree for handling a selection */
    select = gtk_tree_view_get_selection(GTK_TREE_VIEW (categories->tree));
    gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
    g_signal_connect (G_OBJECT (select), "changed", G_CALLBACK (ftd_gui_categories_callback_changed), NULL);

    gtk_container_add (GTK_CONTAINER(categories->widget), categories->tree);

    cellRenderer = gtk_cell_renderer_text_new();
    treeViewColumn = gtk_tree_view_column_new_with_attributes ("cat",cellRenderer,"text",0,NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW(categories->tree),treeViewColumn);

    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (categories->tree), FALSE);
    gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(categories->tree), TRUE);

    gtk_widget_show(categories->widget);
    gtk_widget_show(categories->tree);

    ftd_gui_categories_fill();

    g_signal_connect (categories->tree, "button-release-event", G_CALLBACK(ftd_gui_categories_rmb_click), gui);
}

void
ftd_gui_categories_fill(void)
{
    FtdGuiCategories    *categories;
    GtkTreeIter          treeIter;
    GtkTreeIter          treeIterPar;
    FtdCategoryList     *list;

    /* Vul onze list met data */
    g_assert(gui);
    g_assert(gui->worksheet);
    g_assert(gui->worksheet->sidebar);
    categories = gui->worksheet->sidebar->categories;
    gtk_tree_store_clear(categories->treestore);

    list = ftd_categories_get();
    while (list) {
        FtdCategory *cat = (FtdCategory *) ftd_list_value(list);
        char *bericht;

        g_assert(cat);

        if (cat->header) {
            // We hebben met een top level list element te maken
            gtk_tree_store_insert(categories->treestore,&treeIter,NULL,-1);
        } else {
            // Zoek de parent
            FtdCategory *catParent = ftd_category_get_parent(cat->cat);
            FtdCategory *catParentList;

            if (catParent == NULL) {
                g_warning("ftd_gui_categories_new(): Kan parent categorie niet vinden!");
                list = ftd_list_next(list);
                continue;
            }

            if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(categories->treestore), &treeIterPar)) {
                g_warning("ftd_gui_categories_new(): Kan parent niet vinden in de lijst. Je mag dit bericht niet zien!\n");
                list = ftd_list_next(list);
                continue;
            }

            gtk_tree_model_get(GTK_TREE_MODEL(categories->treestore), &treeIterPar, 1, &catParentList, -1);
            if (catParent != catParentList) {
                gboolean found = FALSE;
                while (gtk_tree_model_iter_next(GTK_TREE_MODEL(categories->treestore), &treeIterPar)) {
                    gtk_tree_model_get(GTK_TREE_MODEL(categories->treestore), &treeIterPar, 1, &catParentList, -1);

                    if (catParent == catParentList) {
                        found = TRUE;
                        break;
                    }
                }

                if (!found) {
                    g_warning("ftd_gui_category_new(): hm..something went awfully wrong\n");
                    list = ftd_list_next(list);
                    continue;
                }
            }

            gtk_tree_store_insert(categories->treestore,&treeIter,&treeIterPar,-1);
        }

        bericht = (char *) g_malloc (ftd_string_length(cat->name) + 9);
        if (cat->aantalPostings > 0) {
            snprintf(bericht, ftd_string_length(cat->name) + 8, "%s (%i)",
                ftd_string_value(cat->name), cat->aantalPostings);
        } else {
            snprintf(bericht, ftd_string_length(cat->name) + 8, "%s",
                ftd_string_value(cat->name));
        }

        gtk_tree_store_set(categories->treestore,&treeIter,
                            0, bericht,
                            1, cat, -1);
        g_free(bericht);

        list = ftd_list_next(list);
    }

    /* expand tree view */
    gtk_tree_view_expand_all(GTK_TREE_VIEW(categories->tree));
}

void
ftd_gui_categories_callback_changed(GtkTreeSelection *selection, gpointer data)
{
    FtdList *tasks = NULL;
    FtdStatusTask *task;
    GtkTreeIter iter;
    GtkTreeModel *model;

    if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
        task = (FtdStatusTask *) g_malloc0(sizeof(FtdStatusTask));
        task->tekst = ftd_string_new("Samenstellen van lijst");
        tasks = ftd_list_append(tasks, task);

        task = (FtdStatusTask *) g_malloc0(sizeof(FtdStatusTask));
        task->tekst = ftd_string_new("Laden van lijst");
        tasks = ftd_list_append(tasks, task);

        ftd_gui_status_new(tasks, gui->window);

        while (gtk_events_pending ())
            gtk_main_iteration ();

        g_idle_add(ftd_gui_categories_callback_do_changed, selection);
    }
}

gboolean
ftd_gui_categories_callback_do_changed(gpointer data)
{
    GtkTreeIter iter;
    GtkTreeModel *model;
    GtkTreeSelection *selection = (GtkTreeSelection *) data;

    if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
        FtdCategory *cat;
        FtdFilter *nieuwFilter;
        FTDEventlist *eventlist;
        FtdFilter *filter;
        gboolean updated;   // Voorkom onnodig hergeneren van de lijst
        int pagenum;
        char *xslt_path;
#ifndef NO_EXTERNAL_BROWSER
        FtdString *uitvoer;
#endif

        eventlist = ftd_eventlist_get();
        filter = ftd_eventlist_get_filter(eventlist);
        updated = FALSE;

        gtk_tree_model_get (model, &iter, 1, &cat, -1);

        g_assert (cat);

        if (filter->veld != FTDEVENT_SORT_DATUM) { updated = TRUE; }
        if (filter->asc != FALSE ) { updated = TRUE; }
        if (filter->cat != cat->filter->cat) { updated = TRUE; }
        if (filter->title != NULL) { updated = TRUE; }
        if (filter->poster != NULL) { updated = TRUE; }
        if (filter->postId != 0) { updated = TRUE; }
        if (filter->prevCheck != (time_t) 0) { updated = TRUE; }
        if (filter->categoriseerd != FALSE) { updated = TRUE; }
        if (!filter->tags && cat->filter->tags ) { updated = TRUE; }
        if (filter->tags && !cat->filter->tags ) { updated = TRUE; }
        if (!updated && filter->tags && cat->filter->tags ) {
            FtdList *taglist1 = filter->tags;
            FtdList *taglist2 = cat->filter->tags;
            if( ftd_list_length( taglist1 ) != ftd_list_length( taglist2 ) ) {
                updated = TRUE;
            }
            else {
                while( taglist1 ) {
                    FtdString *tag1 = ftd_list_value( taglist1 );

                    gboolean inlist = FALSE;
                    taglist2 = cat->filter->tags;
                    while( taglist2 ) {
                        FtdString *tag2 = ftd_list_value( taglist2 );

                        if( !strcmp( ftd_string_value( tag1 ), ftd_string_value( tag2 ) ) ) {
                            inlist = TRUE;
                            break;
                        }

                        taglist2 = ftd_list_next( taglist2 );
                    }

                    if( !inlist ) {
                        updated = TRUE;
                        break;
                    }

                    taglist1 = ftd_list_next( taglist1 );
                }
            }
        }
        if (!filter->extra_tag && cat->filter->extra_tag ) { updated = TRUE; }
        if (filter->extra_tag && !cat->filter->extra_tag ) { updated = TRUE; }
        if (filter->extra_tag && cat->filter->extra_tag ) {
            if (strcmp(ftd_string_value(filter->extra_tag), ftd_string_value(cat->filter->extra_tag))) {
                updated = TRUE;
            }
        }

//        if (cat->header) { updated = FALSE; }

        // Als er niets gewijzigd is dan weggaan uit deze routine
        if (!updated) {
            ftd_gui_status_push();
            ftd_gui_status_push();
            g_object_unref(eventlist);
            return FALSE;
        }

        nieuwFilter = ftd_filter_new_filter();
        nieuwFilter->veld = FTDEVENT_SORT_DATUM;
        nieuwFilter->asc = FALSE;
        nieuwFilter->cat = cat->filter->cat;
        nieuwFilter->sCat = cat->filter->sCat;
        if (ftd_config_get()->groupFilter) {
            nieuwFilter->groupFilterList = ftd_splitted_list_duplicate(ftd_config_get()->groupFilterList);
        }

        if (cat->filter->tags) {
            FtdList *list = cat->filter->tags;
            while(list) {
                FtdString *tag = ftd_list_value(list);
                nieuwFilter->tags = ftd_list_append(nieuwFilter->tags, ftd_string_new(ftd_string_value(tag)));
                list = ftd_list_next(list);
            }
        }

        if (cat->filter->extra_tag) {
            nieuwFilter->extra_tag = ftd_string_new(ftd_string_value(cat->filter->extra_tag));
        }

        nieuwFilter->statusList = ftd_gui_status_filter_get_filter();

        ftd_eventlist_apply_filter(eventlist, nieuwFilter);
        g_object_unref(eventlist);
        ftd_filter_free_filter(nieuwFilter);

#ifndef NO_EXTERNAL_BROWSER
        uitvoer = ftd_events_sort_filtered(ftd_gui_parse);

        if (uitvoer == NULL) {
            ftd_gui_status_push();
            ftd_gui_status_push();
            g_warning("ftd_gui_categories_callback_do_changed(): Sorteren van lijst mislukt\n");
            return FALSE;
        }

        xslt_path = XSLT_TYPE_LIST_TOTAL;

        ftd_gui_xslt_process(uitvoer, xslt_path, HTML_LIST_FILE);

        g_free(xslt_path);
        ftd_string_free (uitvoer);
#endif

        ftd_gui_status_push();

        // Kijk of we wel op het juiste tabblad actief zijn
        pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(gui->worksheet->center->widget), gui->worksheet->center->eventlist->widget);
        gtk_notebook_set_current_page(GTK_NOTEBOOK(gui->worksheet->center->widget), pagenum);

        ftd_gui_center_eventlist_show (NULL);
    } else {
        // We horen hier normaalgesproken nooit te komen..
        ftd_gui_status_push();
        ftd_gui_status_push();
    }

    return FALSE;
}

static void
ftd_gui_categories_bewerk(GtkWidget *caller, gpointer data)
{
    GtkTreeIter iter;
    GtkTreeModel *model;
    GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (gui->worksheet->sidebar->categories->tree));

    if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
        FtdCategory *cat;
        GtkListStore *store;
        const char *name;
        int pagenum;

        gtk_tree_model_get (model, &iter, 1, &cat, -1);

        if (cat->header) {
            ftd_gui_dialog_show(NULL, "Het is niet mogelijk om hoofdcategorien te verwijderen.", gui->window);
            return;
        }

        ftd_gui_callback_config(NULL, NULL);

        pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(gui->config->notebook), gui->config->catfilters->widget);
        gtk_notebook_set_current_page(GTK_NOTEBOOK(gui->config->notebook), pagenum);
        gtk_notebook_set_current_page(GTK_NOTEBOOK(gui->config->catfilters->widget), cat->cat);

        switch (cat->cat) {
            case 0:
                store = gui->config->catfilters->lststoreCat0Filters;
                selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (gui->config->catfilters->lstCat0Filters));
                break;
            case 1:
                store = gui->config->catfilters->lststoreCat1Filters;
                selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (gui->config->catfilters->lstCat1Filters));
                break;
            case 2:
                store = gui->config->catfilters->lststoreCat2Filters;
                selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (gui->config->catfilters->lstCat2Filters));
                break;
            case 3:
                store = gui->config->catfilters->lststoreCat3Filters;
                selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (gui->config->catfilters->lstCat3Filters));
                break;
            default:
                g_print(__FILE__":%i We mogen hier niet geraken!\n", __LINE__);
                ftd_gui_config_callback_ok(NULL, gui->config);
                return;
        }

        g_assert(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));

        while (TRUE) {
            gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &name, -1);

            if (strcmp(name, ftd_string_value(cat->filter->filterNaam)) == 0) {
                gtk_tree_selection_select_iter(selection, &iter);
            }

            if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter)) {
                break;
            }
        }
    }
}

static void
ftd_gui_categories_verwijder(GtkWidget *caller, gpointer data)
{
    GtkTreeIter iter;
    GtkTreeModel *model;
    GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (gui->worksheet->sidebar->categories->tree));

    // Selecteer het huidige filter in het config venster
    ftd_gui_categories_bewerk(NULL, NULL);

    if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
        FtdCategory *cat;

        gtk_tree_model_get (model, &iter, 1, &cat, -1);

        if (cat->header) {
            return;
        }

        switch(cat->cat) {
            case 0:
                gtk_button_clicked(GTK_BUTTON(gui->config->catfilters->btnCat0Delete));
                break;
            case 1:
                gtk_button_clicked(GTK_BUTTON(gui->config->catfilters->btnCat1Delete));
                break;
            case 2:
                gtk_button_clicked(GTK_BUTTON(gui->config->catfilters->btnCat2Delete));
                break;
            case 3:
                gtk_button_clicked(GTK_BUTTON(gui->config->catfilters->btnCat3Delete));
                break;
            default:
                g_error("Onbekende cat: %i\n", cat->cat);
        }

        ftd_gui_config_callback_ok(NULL, gui->config);
    }
}

static gboolean
ftd_gui_categories_rmb_click (GtkWidget *caller, GdkEventButton *event, gpointer data)
{
    if (event->button == 1) {
        // Toon het postoverzicht indien deze nog niet actief was
        int pagenum = gtk_notebook_page_num(GTK_NOTEBOOK(gui->worksheet->center->widget), gui->worksheet->center->eventlist->widget);
        gtk_notebook_set_current_page(GTK_NOTEBOOK(gui->worksheet->center->widget), pagenum);
    }

    if (event->button == 3) {
        // Toon contextmenu
        GtkWidget *menu = gtk_menu_new();
        GtkWidget *item;

        item = gtk_menu_item_new_with_label("Verwijder geselecteerd filter");
        g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(ftd_gui_categories_verwijder), NULL);
        gtk_widget_show(item);
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);

        item = gtk_menu_item_new_with_label("Bewerk geselecteerd filter");
        g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(ftd_gui_categories_bewerk), NULL);
        gtk_widget_show(item);
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);

        gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());

        return TRUE;
    } else {
        return FALSE;
    }
}
