/* ====================================================================
 * 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 "ftd4linux.h"
#include "ftd_app_core.h"
#include "ftd_config.h"
#include "ftd_events.h"
#include "ftd_event.h"

/**
 * Voegt het event toe aan de watchlist.
 *
 * @arg     postid      Het FTD-nummer van het toe te voegen event.
 *
 * @return  True indien het event is toegevoegd.
 */
gboolean
ftd_watchlist_add(int postid)
{
    char waarde[16];

    g_assert(core);
    g_assert(core->config);

    // Hebben we wel een 'nuttige' waarde opgekregen ?
    if (postid <= 0) {
        return FALSE;
    }

    // Kijk eerst of het betreffende postid reeds voorkomt in de watchlist
    if (ftd_watchlist_is_in_list(postid)) {
        return FALSE;
    }

    // Controle is geslaagd, toevoegen maar
    snprintf(waarde, sizeof(waarde), "%i", postid);
    core->config->watchlist = ftd_list_append(core->config->watchlist, ftd_string_new(waarde));

    ftd_config_save();

    return TRUE;
}

/**
 * Haalt een event van de watchlist af.
 *
 * @arg     postid      Het FTD-nummer van het te verwijderen event.
 *
 * @return  True indien het event van de watchlist afgehaald werd.
 */
gboolean
ftd_watchlist_remove(int postid)
{
    FtdList *list;
    g_assert(core);
    g_assert(core->config);

    // Kijk of het postid voorkomt in de lijst
    list = core->config->watchlist;

    while (list) {
        int nummer;
        FtdString *watchlist = ftd_list_value(list);
        g_assert(watchlist);

        nummer = atoi(ftd_string_value(watchlist));
        if (nummer == postid) {
            // bingo! removen maar
            core->config->watchlist = ftd_list_remove(core->config->watchlist, watchlist);
            ftd_string_free(watchlist);

            ftd_config_save();

            return TRUE;
        }
        list = ftd_list_next(list);
    }

    // Als we hier zijn beland is het verwijderen mislukt
    return FALSE;
}

/**
 * Maakt de watchlist leeg.
 */
void
ftd_watchlist_clear(void)
{
    FtdList *list;
    g_assert(core);
    g_assert(core->config);

    // Verwijder alles uit de lijst
    list = core->config->watchlist;

    while (list) {
        FtdString *watchlist = ftd_list_value(list);
        g_assert(watchlist);

        ftd_string_free(watchlist);
        list = ftd_list_next(list);
    }

    ftd_list_free(core->config->watchlist);
    core->config->watchlist = NULL;

    ftd_config_save();
}

/**
 * Kijkt of een event in de watchlist zit.
 *
 * @arg     postingid       Het FTD-nummer van het event.
 *
 * @return  True indien dit event in de watchlist zit.
 */
gboolean
ftd_watchlist_is_in_list(int postingid)
{
    FtdList *list;

    g_assert(core);
    g_assert(core->config);

    // Zoek het element op in de lijst
    list = core->config->watchlist;

    while (list) {
        int nummer;
        FtdString *watchlist = ftd_list_value(list);
        g_assert(watchlist);

        nummer = atoi(ftd_string_value(watchlist));

        if (nummer == postingid) {
            return TRUE;
        }
        list = ftd_list_next(list);
    }

    // Element niet gevonden in lijst
    return FALSE;
}

/**
 * Geeft een XML gecodeerde string met de gegevens van de watchlist.
 *
 * @return  Een nieuwe string met in XML gecodeerd de gegevens van de watchlist.
 */
FtdString *
ftd_watchlist_print(void)
{
    FtdString *uitvoer = ftd_string_new("");
    FtdList *list;
    char buf[1024];

    g_assert(core);
    g_assert(core->config);

    list = core->config->watchlist;
    while (list) {
        int nummer;
        FtdString *watchlist = ftd_list_value(list);
        g_assert(watchlist);

        nummer = atoi(ftd_string_value(watchlist));

        snprintf(buf, sizeof(buf), "\t<Watchlist>%i</Watchlist>\n", nummer);
        uitvoer = ftd_string_append(uitvoer, buf);
        list = ftd_list_next(list);
    }

    return uitvoer;
}

/**
 * Geeft de status van de watchlist weer.
 *
 * @return  De status van de watchlist.
 *
 * @see ::FtdAppCore.watchlist_state
 */
int
ftd_watchlist_get_state(void)
{
    g_assert(core);

    return core->watchlist_state;
}

/**
 * Stelt de status van de watchlist in.
 *
 * @arg     value       De nieuwe status van de watchlist.
 *
 * @see ::FtdAppCore.watchlist_state
 */
void
ftd_watchlist_set_state(int value)
{
    g_assert(core);
    core->watchlist_state = value;
}

/**
 * Geeft de watchlist weer.
 * Geef het resultaat niet vrij!
 *
 * @return  Een lijst met ::FtdString pointers met daarin de FTD-nummers van de events in de watchlist.
 */
FtdList *
ftd_watchlist_get(void)
{
    g_assert(core);
    g_assert(core->config);
    return core->config->watchlist;
}

/**
 * Haalt de watchlist op van de FTD server
 *
 * @arg     errmsg              Een eventueel foutbericht van de server wordt hier in geplaatst.
 *
 * @return  Een fout-code die aangeeft of het downloaden succesvol was verlopen
 */
FtdErrorCode
ftd_watchlist_download(char **errmsg)
{
    FtdList         *params = NULL;
    FtdString       *uitvoer;
    FtdErrorCode     retval;
    FtdList         *list, *list_total;
    FtdEvent        *event;
    FTDEventlist    *eventlist;

    params = ftd_list_append(params, ftd_http_parameter_new("mode", "load"));
    retval = ftd_http_curl_execute(FTD_URL_WATCHLIST, params, TRUE, &uitvoer, TRUE, NULL, FALSE);
    ftd_http_parameter_free_all(params);

    if (retval != ERROR_NONE) {
        if (retval == ERROR_MSG) {
            *errmsg = g_strdup(ftd_string_value(uitvoer));
        } else {
            *errmsg = NULL;
        }

        ftd_string_free(uitvoer);

        return retval;
    }

    /* We hebben nu een string in de trand van |199391*1|199378*1|
     * Hiermee wordt aangeduid dat er 2 postings in de watchlist actief zijn
     * namelijk 199391 en 199378 en beiden vallen ze onder watchlist-categorie 1
     * Onder FTD 3.7 is de watchlist namelijk nog opgesplitst in categorien.
     * Binnen FTD4Linux doen we hier niet aan, dus houden we ons aan categorie nummer 1 */
    list = list_total = ftd_splitted_list_split(ftd_string_value(uitvoer));

    ftd_string_free(uitvoer);

    eventlist = ftd_eventlist_get();

    while (list) {
        FtdString *entry = ftd_list_value(list);
        int postid = atoi(ftd_string_value(entry)); // Het stukje *1 wordt automatisch genegeerd hiermee

        // Kennen we deze posting ?
        event = ftd_eventlist_lookup_id(eventlist, postid);
        if (!event) {
            event = ftd_eventinfo_findpost(postid);
            if (!event) {
                // posting valt ook niet op de server te vinden, negeren
                g_warning("ftd_watchlist_download(): posting %i valt niet op de FTD server te vinden\n", postid);
                list = ftd_list_next(list);
                continue;
            }

            ftd_eventlist_add_or_replace_event(eventlist, event);
            ftd_eventlist_save(eventlist);
        }

        ftd_event_free(event);

        if (!ftd_watchlist_is_in_list(postid)) {
            ftd_watchlist_add(postid);
        }

        list = ftd_list_next(list);
    }

    g_object_unref(eventlist);

    *errmsg = NULL;

    return ERROR_NONE;
}

/**
 * Bewaard de watchlist op de FTD server
 *
 * @arg     errmsg              Een eventueel foutbericht van de server wordt hier in geplaatst.
 *
 * @return  Een fout-code die aangeeft of het uploaden succesvol was verlopen
 */
FtdErrorCode
ftd_watchlist_upload(char **errmsg)
{
    FtdList         *params = NULL;
    FtdString       *uitvoer;
    FtdErrorCode     retval;
    FtdList         *list;
    char            *data = NULL;

    // We moeten een string maken in de trand van |199391*1|199378*1|
    // Zoek het element op in de lijst
    list = core->config->watchlist;

    if (list == NULL) {
        return ERROR_NONE;
    }

    while (list) {
        FtdString *watchlist = ftd_list_value(list);

        g_assert(watchlist);

        if (!data) {
            data = g_strdup_printf("|%s*1|", ftd_string_value(watchlist));
        } else {
            char *tmp;
            tmp = g_strdup_printf("%s%s*1|", data, ftd_string_value(watchlist));
            g_free(data);
            data = tmp;
        }

        list = ftd_list_next(list);
    }

    params = ftd_list_append(params, ftd_http_parameter_new("mode", "save"));
    params = ftd_list_append(params, ftd_http_parameter_new("data", data));
    retval = ftd_http_curl_execute(FTD_URL_WATCHLIST, params, TRUE, &uitvoer, TRUE, NULL, TRUE);
    ftd_http_parameter_free_all(params);
    g_free(data);

    if (retval != ERROR_NONE) {
        if (retval == ERROR_MSG) {
            *errmsg = g_strdup(ftd_string_value(uitvoer));
        } else {
            *errmsg = NULL;
        }

        ftd_string_free(uitvoer);

        return retval;
    }

    *errmsg = NULL;

    if (strcmp(ftd_string_value(uitvoer), "OK") != 0) {
        ftd_string_free(uitvoer);

        return ERROR_RES;
    }

    ftd_string_free(uitvoer);

    return ERROR_NONE;
}
