/*
 *  call-seq:
 *     IndexReader.new(dir) -> index_reader
 *
 *  Create a new IndexReader. You can either pass a string path to a
 *  file-system directory or an actual Ferret::Store::Directory object. For
 *  example;
 *
 *    dir = RAMDirectory.new()
 *    iw = IndexReader.new(dir)
 *
 *    dir = FSDirectory.new("/path/to/index")
 *    iw = IndexReader.new(dir)
 *
 *    iw = IndexReader.new("/path/to/index")
 *
 *  You can also create a what used to be known as a MultiReader by passing an
 *  array of IndexReader objects, Ferret::Store::Directory objects or
 *  file-system paths;
 *
 *    iw = IndexReader.new([dir, dir2, dir3])
 *
 *    iw = IndexReader.new([reader1, reader2, reader3])
 *
 *    iw = IndexReader.new(["/path/to/index1", "/path/to/index2"])
 */
static VALUE
frt_ir_init(VALUE self, VALUE rdir)
{
    Store *store = NULL;
    IndexReader *ir;
    int i;
    FieldInfos *fis;
    VALUE rfield_num_map = rb_hash_new();

    if (TYPE(rdir) == T_ARRAY) {
        VALUE rdirs = rdir;
        const int reader_cnt = RARRAY(rdir)->len;
        IndexReader **sub_readers = ALLOC_N(IndexReader *, reader_cnt);
        int i;
        for (i = 0; i < reader_cnt; i++) {
            rdir = RARRAY(rdirs)->ptr[i];
            switch (TYPE(rdir)) {
                case T_DATA:
                    if (CLASS_OF(rdir) == cIndexReader) {
                        Data_Get_Struct(rdir, IndexReader, sub_readers[i]);
                        REF(sub_readers[i]);
                        continue;
                    } else if (RTEST(rb_obj_is_kind_of(rdir, cDirectory))) {
                        store = DATA_PTR(rdir);
                    } else {
                        rb_raise(rb_eArgError, "A Multi-IndexReader can only "
                                 "be created from other IndexReaders, "
                                 "Directory objects or file-system paths. "
                                 "Not %s",
                                 RSTRING(rb_obj_as_string(rdir))->ptr);
                    }
                    break;
                case T_STRING:
                    frt_create_dir(rdir);
                    store = open_fs_store(RSTRING(rdir)->ptr);
                    DEREF(store);
                    break;
                default:
                    rb_raise(rb_eArgError, "%s isn't a valid directory "
                             "argument. You should use either a String or "
                             "a Directory",
                             RSTRING(rb_obj_as_string(rdir))->ptr);
                    break;
            }
            sub_readers[i] = ir_open(store);
        }
        ir = mr_open(sub_readers, reader_cnt);
        Frt_Wrap_Struct(self, &frt_mr_mark, &frt_ir_free, ir);
    } else {
        switch (TYPE(rdir)) {
            case T_DATA:
                store = DATA_PTR(rdir);
                break;
            case T_STRING:
                frt_create_dir(rdir);
                store = open_fs_store(RSTRING(rdir)->ptr);
                DEREF(store);
                break;
            default:
                rb_raise(rb_eArgError, "%s isn't a valid directory argument. "
                         "You should use either a String or a Directory",
                         RSTRING(rb_obj_as_string(rdir))->ptr);
                break;
        }
        ir = ir_open(store);
        Frt_Wrap_Struct(self, &frt_ir_mark, &frt_ir_free, ir);
    }
    object_add(ir, self);

    fis = ir->fis;
    for (i = 0; i < fis->size; i++) {
        FieldInfo *fi = fis->fields[i];
        rb_hash_aset(rfield_num_map,
                     ID2SYM(rb_intern(fi->name)),
                     INT2FIX(fi->number));
    }
    rb_ivar_set(self, id_fld_num_map, rfield_num_map);

    return self;
}