/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define C_TESTLUCY_TESTSERIESMATCHER
#define TESTLUCY_USE_SHORT_NAMES
#include "Lucy/Util/ToolSet.h"

#include "Clownfish/TestHarness/TestBatchRunner.h"
#include "Lucy/Test.h"
#include "Lucy/Test/Search/TestSeriesMatcher.h"
#include "Lucy/Search/BitVecMatcher.h"
#include "Lucy/Search/SeriesMatcher.h"

TestSeriesMatcher*
TestSeriesMatcher_new() {
    return (TestSeriesMatcher*)Class_Make_Obj(TESTSERIESMATCHER);
}

static SeriesMatcher*
S_make_series_matcher(I32Array *doc_ids, I32Array *offsets, int32_t doc_max) {
    size_t   num_doc_ids  = I32Arr_Get_Size(doc_ids);
    size_t   num_matchers = I32Arr_Get_Size(offsets);
    Vector  *matchers     = Vec_new(num_matchers);
    size_t   tick         = 0;

    // Divvy up doc_ids by segment into BitVectors.
    for (size_t i = 0; i < num_matchers; i++) {
        int32_t offset = I32Arr_Get(offsets, i);
        int32_t max    = i == num_matchers - 1
                         ? doc_max + 1
                         : I32Arr_Get(offsets, i + 1);
        BitVector *bit_vec = BitVec_new((size_t)(max - offset));
        while (tick < num_doc_ids) {
            int32_t doc_id = I32Arr_Get(doc_ids, tick);
            if (doc_id > max) { break; }
            else               { tick++; }
            BitVec_Set(bit_vec, (size_t)(doc_id - offset));
        }
        Vec_Push(matchers, (Obj*)BitVecMatcher_new(bit_vec));
        DECREF(bit_vec);
    }

    SeriesMatcher *series_matcher = SeriesMatcher_new(matchers, offsets);
    DECREF(matchers);
    return series_matcher;
}

static I32Array*
S_generate_match_list(int32_t first, int32_t max, int32_t doc_inc) {
    int32_t  count     = (max - first + doc_inc - 1) / doc_inc;
    int32_t *doc_ids   = (int32_t*)MALLOCATE((size_t)count * sizeof(int32_t));
    int32_t  doc_id    = first;
    int32_t  i         = 0;

    for (; doc_id < max; doc_id += doc_inc, i++) {
        doc_ids[i] = doc_id;
    }
    if (i != count) { THROW(ERR, "Screwed up somehow: %i32 %i32", i, count); }

    return I32Arr_new_steal(doc_ids, (size_t)count);
}

static void
S_do_test_matrix(TestBatchRunner *runner, int32_t doc_max, int32_t first_doc_id,
                 int32_t doc_inc, int32_t offset_inc) {
    I32Array *doc_ids
        = S_generate_match_list(first_doc_id, doc_max, doc_inc);
    I32Array *offsets
        = S_generate_match_list(0, doc_max, offset_inc);
    SeriesMatcher *series_matcher
        = S_make_series_matcher(doc_ids, offsets, doc_max);
    size_t num_in_agreement = 0;
    int32_t got;

    while (0 != (got = SeriesMatcher_Next(series_matcher))) {
        if (got != I32Arr_Get(doc_ids, num_in_agreement)) { break; }
        num_in_agreement++;
    }
    TEST_UINT_EQ(runner, num_in_agreement, I32Arr_Get_Size(doc_ids),
                 "doc_max=%d first_doc_id=%d doc_inc=%d offset_inc=%d",
                 doc_max, first_doc_id, doc_inc, offset_inc);

    DECREF(doc_ids);
    DECREF(offsets);
    DECREF(series_matcher);
}

static void
test_matrix(TestBatchRunner *runner) {
    int32_t doc_max_nums[]     = { 10, 100, 1000, 0 };
    int32_t first_doc_ids[]    = { 1, 2, 10, 0 };
    int32_t doc_inc_nums[]     = { 20, 13, 9, 4, 2, 0 };
    int32_t offset_inc_nums[]  = { 7, 29, 71, 0 };
    int32_t a, b, c, d;

    for (a = 0; doc_max_nums[a] != 0; a++) {
        for (b = 0; first_doc_ids[b] != 0; b++) {
            for (c = 0; doc_inc_nums[c] != 0; c++) {
                for (d = 0; offset_inc_nums[d] != 0; d++) {
                    int32_t doc_max        = doc_max_nums[a];
                    int32_t first_doc_id   = first_doc_ids[b];
                    int32_t doc_inc        = doc_inc_nums[c];
                    int32_t offset_inc     = offset_inc_nums[d];
                    if (first_doc_id > doc_max) {
                        continue;
                    }
                    else {
                        S_do_test_matrix(runner, doc_max, first_doc_id,
                                         doc_inc, offset_inc);
                    }
                }
            }
        }
    }
}

void
TestSeriesMatcher_Run_IMP(TestSeriesMatcher *self, TestBatchRunner *runner) {
    TestBatchRunner_Plan(runner, (TestBatch*)self, 135);
    test_matrix(runner);
}


