#define C_KINO_MATCHER
#define KINO_USE_SHORT_NAMES
#define CHY_USE_SHORT_NAMES

#include "KinoSearch/Search/Matcher.h"
#include "KinoSearch/Object/Err.h"
#include "KinoSearch/Object/VTable.h"
#include "KinoSearch/Search/Collector.h"

Matcher*
Matcher_init(Matcher *self)
{
    ABSTRACT_CLASS_CHECK(self, MATCHER);
    return self;
}

int32_t
Matcher_advance(Matcher *self, int32_t target) 
{
    while (1) {
        int32_t doc_id = Matcher_Next(self);
        if (doc_id == 0 || doc_id >= target)
            return doc_id; 
    }
}

void
Matcher_collect(Matcher *self, Collector *collector, Matcher *deletions)
{
    int32_t doc_id         = 0;
    int32_t next_deletion  = deletions ? 0 : I32_MAX;

    Coll_Set_Matcher(collector, self);

    // Execute scoring loop. 
    while (1) {
        if (doc_id > next_deletion) {
            next_deletion = Matcher_Advance(deletions, doc_id);
            if (next_deletion == 0) { next_deletion = I32_MAX; }
            continue;
        }
        else if (doc_id == next_deletion) {
            // Skip past deletions. 
            while (doc_id == next_deletion) {
                // Artifically advance matcher. 
                while (doc_id == next_deletion) {
                    doc_id++;
                    next_deletion = Matcher_Advance(deletions, doc_id);
                    if (next_deletion == 0) { next_deletion = I32_MAX; }
                }
                // Verify that the artificial advance actually worked. 
                doc_id = Matcher_Advance(self, doc_id);
                if (doc_id > next_deletion) {
                    next_deletion = Matcher_Advance(deletions, doc_id);
                }
            }
        }
        else {
            doc_id = Matcher_Advance(self, doc_id + 1);
            if (doc_id >= next_deletion) { 
                next_deletion = Matcher_Advance(deletions, doc_id);
                if (doc_id == next_deletion) { continue; }
            }
        }

        if (doc_id) {
            Coll_Collect(collector, doc_id);
        }
        else { 
            break; 
        }
    }

    Coll_Set_Matcher(collector, NULL);
}

/* Copyright 2006-2011 Marvin Humphrey
 *
 * This program is free software; you can redistribute it and/or modify
 * under the same terms as Perl itself.
 */

