/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */

/*
 *  Copyright (C) 2006 Eriko Sato
 *
 *  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; either version 2, or (at your option)
 *  any later version.
 *
 *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "kz-rb-ext.h"
#include "kazehakase.h"

static VALUE
rb_kz_conf_get(int argc, VALUE *argv, VALUE self)
{
    VALUE rb_section, rb_key, rb_type;
    VALUE rb_value = Qnil;
    gchar *section, *key;
    int n, type;

    n = rb_scan_args(argc, argv, "21", &rb_section, &rb_key, &rb_type);

    if (NIL_P(rb_type)) {
        type = KZ_PROFILE_VALUE_TYPE_STRING;
    } else {
        type = NUM2INT(rb_type);
        if (type < KZ_PROFILE_VALUE_TYPE_BOOL ||
            type > KZ_PROFILE_VALUE_TYPE_ARRAY) {
            rb_raise(rb_eTypeError, "invalid type: %d", type);
        }
    }

    section = RVAL2CSTR(rb_section);
    key = RVAL2CSTR(rb_key);

    switch (type) {
      case KZ_PROFILE_VALUE_TYPE_BOOL:
      {
          gboolean value;
          if (KZ_CONF_GET(section, key, value, BOOL)) {
              rb_value = CBOOL2RVAL(value);
          }
          break;
      }
      case KZ_PROFILE_VALUE_TYPE_INT:
      {
          gint value;
          if (KZ_CONF_GET(section, key, value, INT)) {
              rb_value = INT2NUM(value);
          }
          break;
      }
      case KZ_PROFILE_VALUE_TYPE_STRING:
      {
          gchar *value;
          value = KZ_CONF_GET_STR(section, key);
          if (value) {
              rb_value = rb_str_new2(value);
              g_free(value);
          }
          break;
      }
      case KZ_PROFILE_VALUE_TYPE_ARRAY:
        rb_raise(rb_eTypeError, "ARRAY type is not supported");
        break;
    }

    return rb_value;
}

static VALUE
rb_kz_conf_set(VALUE self, VALUE rb_section, VALUE rb_key, VALUE rb_value)
{
    VALUE success = Qfalse;
    gchar *section, *key;

    section = RVAL2CSTR(rb_section);
    key = RVAL2CSTR(rb_key);
    
    if (TYPE(rb_value) == T_TRUE || TYPE(rb_value) == T_FALSE) {
        gboolean value = RTEST(rb_value);
        success = KZ_CONF_SET(section, key, value, BOOL);
    } else if (RTEST(rb_obj_is_kind_of(rb_value, rb_cNumeric))) {
        gint value = NUM2INT(rb_value);
        success = KZ_CONF_SET(section, key, value, INT);
    } else if (RTEST(rb_obj_is_kind_of(rb_value, rb_cString))) {
        gchar *value = RVAL2CSTR(rb_value);
        success = KZ_CONF_SET_STR(section, key, value);
    } else if (RTEST(rb_obj_is_kind_of(rb_value, rb_cArray))) {
        rb_raise(rb_eTypeError, "ARRAY type is not supported");
    } else {
        VALUE inspected_rb_value = rb_inspect(rb_value);
        rb_raise(rb_eTypeError, "unsupported value: %s",
                 RVAL2CSTR(inspected_rb_value));
    }
    
    return success;
}

void
Init_kz_rb_conf(VALUE mKz)
{
    VALUE mKzConf;

    mKzConf = rb_define_module_under(mKz, "Conf");

    rb_define_const(mKzConf, "BOOL", INT2NUM(KZ_PROFILE_VALUE_TYPE_BOOL));
    rb_define_const(mKzConf, "INT", INT2NUM(KZ_PROFILE_VALUE_TYPE_INT));
    rb_define_const(mKzConf, "STRING", INT2NUM(KZ_PROFILE_VALUE_TYPE_STRING));
    rb_define_const(mKzConf, "ARRAY", INT2NUM(KZ_PROFILE_VALUE_TYPE_ARRAY));
    
    rb_define_singleton_method(mKzConf, "get", rb_kz_conf_get, -1);
    rb_define_singleton_method(mKzConf, "[]", rb_kz_conf_get, -1);
    rb_define_singleton_method(mKzConf, "set", rb_kz_conf_set, 3);
    rb_define_singleton_method(mKzConf, "[]=", rb_kz_conf_set, 3);
}
