#include "liblocky.h"

#include <assert.h>
#include <stdio.h>


void blky_encoder_feed(blky_encoder_t* enc, uint8_t data) {
  assert(enc);
  assert(enc->block_num  > 0);
  assert(enc->feat_bits  > 0);
  assert(enc->feat_bits <= sizeof(enc->scrap)*8);
  assert(enc->seed       > 0);

  if (enc->count++ == 0) enc->scrap_bits = 1;

  assert(enc->scrap_bits+8 <= 32);
  enc->scrap      |= data << enc->scrap_bits;
  enc->scrap_bits += 8;
}

bool blky_encoder_pop(blky_encoder_t* enc, uint32_t* feat, bool force) {
  assert(enc);
  assert(feat);

  if (force) {
    if (enc->scrap_bits > 0) return false;
  } else {
    if (enc->scrap_bits < enc->feat_bits) return false;
  }

  const uint32_t feat_max = 1 << enc->feat_bits;
  assert(feat_max < enc->block_num);

  enc->seed = blky_numeric_xorshift64(enc->seed);
  *feat     = blky_numeric_hop(enc->block_index, enc->scrap%feat_max, enc->seed)%enc->block_num;

  enc->block_index   = *feat;
  enc->scrap       >>= enc->feat_bits;
  enc->scrap_bits   -= enc->feat_bits;
  return true;
}