/* eurephiadb_session_common.c  --  Common function for handling sessions
 *
 *  GPLv2 only - Copyright (C) 2008 - 2012
 *               David Sommerseth <dazo@users.sourceforge.net>
 *
 *  This program 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; version 2
 *  of the License.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

/**
 * @file   eurephiadb_session_common.c
 * @author David Sommerseth <dazo@users.sourceforge.net>
 * @date   2008-11-28
 *
 * @brief  Common functions for handling eurephia sessions.
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <eurephia_nullsafe.h>
#include <eurephia_context.h>
#include <eurephia_log.h>
#include <eurephia_values.h>
#include <eurephiadb_session_struct.h>
#include <eurephiadb_driver.h>

/**
 * Adds or updates a key in the eurephiaVALUES stack.  Database is updated before the stack is updated.
 * If database fails, the stack is not updated.
 *
 * @param ctx     eurephiaCTX
 * @param session eurephiaSESSION, which contains information about the current user session
 * @param key     key name of the value to be stored
 * @param val     value to be stored
 *
 * @return Returns 1 on success, otherwise 0.
 */
int eDBset_session_value(eurephiaCTX *ctx, eurephiaSESSION *session, const char *key, const char *val) {
        eurephiaVALUES *svals = NULL;

        if( (session == NULL) || (key == NULL) ) {
                return 0;
        }

        DEBUG(ctx, 30, "Function call: eDBset_session_value(ctx, '%s','%s','%s')",
              session->sessionkey, key, val);

        // Create a new session value buffer if it does not exist
        if( session->sessvals == NULL ) {
                session->sessvals = eCreate_value_space(ctx, 10);
                if( session->sessvals == NULL ) {
                        eurephia_log(ctx, LOG_PANIC, 0, "Could not allocate memory for session values");
                        return 0;
                }
        }

        // Check if the session value exists already.  If it does update it, or else add it
        svals = eGet_valuestruct(session->sessvals, key);
        if( (svals == NULL) && (val != NULL) ) {
                DEBUG(ctx, 32, "eDBset_session_value ... New session value: %s = '%s'", key, val);
                // Add a new session value
                if( eDBstore_session_value(ctx, session, SESSVAL_NEW, key, val) ) {
                        DEBUG(ctx, 32, "eDBset_session_value ... Adding value to value stack: %s = '%s'",
                              key, val);
                        // Add value to the stack
                        eAdd_value(ctx, session->sessvals, key, val);

                        DEBUG(ctx, 32, "Registered session variable to session '%s': %s = %s",
                              session->sessionkey, key, val);
                }
        } else if( svals != NULL ) {
                if( (val != NULL) && (strcmp(svals->val, val) == 0) ) {
                        DEBUG(ctx, 32, "Session value not changed('%s','%s','%s)",
                              session->sessionkey, key, val);
                        return 1;
                }
                // Update the value in the stack if database is updated without errors
                if( eDBstore_session_value(ctx, session,(val != NULL ? SESSVAL_UPDATE : SESSVAL_DELETE), key,val)){
                        free_nullsafe(ctx, svals->val);
                        svals->val = strdup_nullsafe(val);
                        DEBUG(ctx, 32, "Session variable updated in session '%s': %s = %s",
                              session->sessionkey, key, val);
                }
        } else if( (svals == NULL) && (val == NULL ) ) {
                DEBUG(ctx, 32, "Ignoring saving new session value '%s' == NULL", key);
        }
        return 1;
}


/**
 * Free up the memory used by a session structure.  This is normally not called directly, but called via the
 * eDBfree_session(...) macro.
 *
 * @param ctx      eurephiaCTX
 * @param session  Pointer to the eurephiaSESSION structure to be freed.
 */
void eDBfree_session_func(eurephiaCTX *ctx, eurephiaSESSION *session) {
        if( session == NULL ) {
                return;
        }
        DEBUG(ctx, 12, "Function call: eDBfree_session(ctx, '%s')", session->sessionkey);
        eFree_values(ctx, session->sessvals);
        free_nullsafe(ctx, session->sessionkey);
        free(session);
}
