/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: hxgprefs.cpp,v 1.3.8.3 2004/07/09 01:48:35 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

#include "hxgprefs.h"
#include "hxgvalue.h"

#include "HXClientTypes.h"

#include <glib.h>
#include <string.h>

/* list of engine preferences */
/* Use a GSList to be more compatible with gconf */
static GSList* g_prefs_list = NULL;

bool
ReadPreference(const char*    pPrekKey,
               unsigned char* pValueBuffer,
               UInt32         bufferLength,
               UInt32*        pUsedBufferLength )
{
    static HXEntry* last_entry = NULL;
    
    if(last_entry)
    {
        const gchar* str_value;
        /* We're being called the second time */
        g_assert(pValueBuffer != NULL);
        g_assert(last_entry != NULL);
        g_assert(*pUsedBufferLength > 0);
        
        HXValue* value = hx_entry_get_value(last_entry);
        str_value = hx_value_get_string(value);
        // printf("read pref(%s) = %s\n", pPrekKey, str_value);
        memcpy((char*)pValueBuffer, str_value, bufferLength);

        last_entry = NULL;
    }
    else
    {        
        HXEntry* entry;
    
        /* We're being called the first time */
        g_assert(pValueBuffer == NULL);

        GSList* iter = g_prefs_list;

        /* Find the preference */
        while(iter)
        {
            const gchar* key;
            entry = (HXEntry*)iter->data;
            key = hx_entry_get_key(entry);
            if(g_ascii_strcasecmp(pPrekKey, key) == 0)
            {
                break;
            }        
        
            iter = g_slist_next(iter);
        }

        if(!iter)
        {
            *pUsedBufferLength = 0;
            // printf("read pref(%s) = not found\n", pPrekKey);
            last_entry = NULL;
            // Preference not found
            return false;
        }
        else
        {
            const gchar* str;
            HXValue* value = hx_entry_get_value(entry);

            str = hx_value_get_string(value);
            if(str && *str)
            {
                *pUsedBufferLength = strlen(str) + 1;
                last_entry = entry;
            }
            else
            {
                *pUsedBufferLength = 0;
                last_entry = NULL;                
            }
        }
    }
        
    return true;
}

bool
WritePreference(const char*          pPrekKey,
                const unsigned char* pValueBuffer,
                UInt32               bufferLength)
{
    GSList* iter = g_prefs_list;
    HXValue* value;
    HXEntry* entry;
    gchar* str_val;
    
    /* Find the preference */
    while(iter)
    {
        entry = (HXEntry*)iter->data;
        if(g_ascii_strcasecmp(pPrekKey, hx_entry_get_key(entry)) == 0)
        {
            break;
        }        
        
        iter = g_slist_next(iter);
    }

    if(!iter)
    {
        /* Doesn't exist -- add it to the list */
        // printf("add pref(%s): %s\n", pPrekKey, pValueBuffer);
        value = hx_value_new(HX_VALUE_STRING);
        str_val = g_strndup((char*)pValueBuffer, bufferLength);
        hx_value_set_string_nocopy(value, str_val);
        entry = hx_entry_new_nocopy(g_strdup(pPrekKey), value);
        g_prefs_list = g_slist_append(g_prefs_list, entry);
    }
    else
    {
        // printf("modify pref(%s): %s\n", pPrekKey, pValueBuffer);
        /* Exist -- overwrite */
        str_val = g_strndup((char*)pValueBuffer, bufferLength);
        value = hx_entry_get_value(entry);
        hx_value_set_string_nocopy(value, str_val);
    }

    return true;
}

bool
DeletePreference(const char* pPrekKey)
{
    GSList* iter = g_prefs_list;
    HXEntry* entry;
    
    /* Find the preference */
    while(iter)
    {
        entry = (HXEntry*)iter->data;
        if(g_ascii_strcasecmp(pPrekKey, hx_entry_get_key(entry)) == 0)
        {
            /* Remove this pref from the list */
            // printf("delete pref(%s)\n", pPrekKey);
            hx_entry_free(entry);
            g_prefs_list = g_slist_delete_link(g_prefs_list, iter);
            return true;
        }        
        
        iter = g_slist_next(iter);
    }

    // printf("delete pref(%s) not found!\n", pPrekKey);
    
    return false;
}


GSList*
hx_prefs_get_all_entries()
{
    return g_prefs_list;
}

HXEntry*
hx_prefs_get_entry(const gchar *key)
{
    HXEntry* entry = NULL;
    HXValue* value;
    gchar* str;
    UInt32 len = 0;
    gboolean result;

    result = ReadPreference(key, NULL, len, &len);
    if(result)
    {
        if(len > 0)
        {
            str = (gchar*)g_malloc(len + 1);
            result = ReadPreference(key, (unsigned char*)str, len, &len);
            if(!result)
            {
                g_free(str);
                return NULL;
            }

            str[len] = '\0';
        }
        else
        {
            g_assert(len == 0);
            str = g_strdup("");
        }

        value = hx_value_new(HX_VALUE_STRING);
        hx_value_set_string(value, str);
        entry = hx_entry_new_nocopy(g_strdup(key), value);
        
        g_free(str);
    }

    return entry;
}

gboolean
hx_prefs_set_entry(const gchar *key, const HXValue* value)
{
    
    if(value)
    { 
        const gchar* str;
        str = hx_value_get_string(value);
        
        // Don't include the terminating NULL
        return WritePreference(key, (const unsigned char*)str, strlen(str));
    }
    else
    {
        return DeletePreference(key);
    }
}

