//
// Created by 马也驰 on 2024/12/22.
//

#include <algorithm>
#include <iostream>
#include <thread>
#include <vector>

#include "../db/slotpage.h"

void printVector(const std::vector<uint32_t>& vec) {
  for (size_t i = 0; i < vec.size(); ++i) {
    std::cout << vec[i] << " ";
  }
  std::cout << std::endl;
}

int test1() {
  SlotCache slot_cache((std::string&)"test_slotpage");

  const size_t blksize = 4096;
  const size_t blknum = 32;
  const size_t slot_content_num = blknum * blksize / sizeof(slot_content);
  slot_content slot_contents[slot_content_num];

  for (int i = 0; i < slot_content_num; i++) {
    slot_contents[i] = {static_cast<uint32_t>(i), static_cast<uint32_t>(i)};
  }
//
//  slot_cache.write_for_test(reinterpret_cast<char*>(slot_contents), slot_content_num*sizeof(slot_content));

  slot_content sc;
  for (int i = 0; i < slot_content_num; i++) {
    slot_cache.get_slot(i, &sc);
    assert(sc.vlog_num == slot_contents[i].vlog_num);
    assert(sc.value_offset == slot_contents[i].vlog_num);
    std::cout << i << std::endl;
  }

  return 1;
}

int test2() {
  SlotCache slot_cache((std::string&)"test_slotpage");

  const size_t blksize = 4096;
  const size_t blknum = 32;
  const size_t slot_content_num = blknum * blksize / sizeof(slot_content);
  slot_content slot_contents[slot_content_num];

  for (int i = 0; i < slot_content_num; i++) {
    slot_contents[i] = {static_cast<uint32_t>(i), static_cast<uint32_t>(i)};
  }
  //
  //  slot_cache.write_for_test(reinterpret_cast<char*>(slot_contents), slot_content_num*sizeof(slot_content));

  slot_content sc1 = {999999999, 999999999};
//  slot_cache.set_slot(100, &sc1);
//  slot_cache.set_slot(1000, &sc1);
//  slot_cache.set_slot(2000, &sc1);

  slot_content sc2 = {0, 0};
  slot_cache.get_slot(100, &sc2);
  assert(sc2.vlog_num == sc1.vlog_num);
  assert(sc2.value_offset == sc1.value_offset);
  slot_cache.get_slot(1000, &sc2);
  assert(sc2.vlog_num == sc1.vlog_num);
  assert(sc2.value_offset == sc1.value_offset);
  slot_cache.get_slot(2000, &sc2);
  assert(sc2.vlog_num == sc1.vlog_num);
  assert(sc2.value_offset == sc1.value_offset);


//  for (int i = 0; i < slot_content_num; i++) {
//    slot_cache.get_slot(i, &sc);
//    assert(sc.vlog_num == slot_contents[i].vlog_num);
//    assert(sc.value_offset == slot_contents[i].vlog_num);
//    std::cout << i << std::endl;
//  }

  return 1;
}


void process_slots(SlotCache& slot_cache,
                   const slot_content* slot_contents,
                   size_t start, size_t end,
                   std::vector<uint32_t>& slots) {
  slot_content sc;
  for (size_t i = start; i < end; ++i) {
    slot_cache.get_slot(i, &sc);
    assert(sc.vlog_num == slot_contents[i].vlog_num);
    assert(sc.value_offset == slot_contents[i].vlog_num);

    slots.push_back(sc.vlog_num);
  }
}

int test3() {
  SlotCache slot_cache((std::string&)("test_slotpage"));

  const size_t blksize = 4096;
  const size_t blknum = 32;
  const size_t slot_content_num = blknum * blksize / sizeof(slot_content);
  slot_content slot_contents[slot_content_num];

  for (size_t i = 0; i < slot_content_num; i++) {
    slot_contents[i] = {static_cast<uint32_t>(i), static_cast<uint32_t>(i)};
  }

  std::vector<uint32_t> slots1;
  std::vector<uint32_t> slots2;

  // 创建两个线程分别处理 slots1 和 slots2
  std::thread t1(process_slots, std::ref(slot_cache), slot_contents, 0, 100, std::ref(slots1));
  std::thread t2(process_slots, std::ref(slot_cache), slot_contents, 100, 200, std::ref(slots2));

  // 等待线程完成
  t1.join();
  t2.join();

  // 打印两个 vector 的内容
  std::cout << "Slots1:" << std::endl;
  printVector(slots1);
  std::cout << std::endl;

  std::cout << "Slots2:" << std::endl;
  printVector(slots2);
  std::cout << std::endl;

  // 合并并排序
  std::vector<uint32_t> merged_slots = slots1;
  merged_slots.insert(merged_slots.end(), slots2.begin(), slots2.end());
  std::sort(merged_slots.begin(), merged_slots.end());

  // 打印合并排序后的结果
  std::cout << "Merged and Sorted Slots:" << std::endl;
  printVector(merged_slots);
  std::cout << std::endl;

  return 1;
}


int test4() {
  SlotCache *slot_cache = new SlotCache("test_slotpage");

  slot_content sc = {0, 16};
  slot_cache->set_slot(0, &sc);
  sc = {0, 17};
  slot_cache->set_slot(1, &sc);
  sc = {0, 18};
  slot_cache->set_slot(2, &sc);

  slot_cache->get_slot(0, &sc);
  std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
  slot_cache->get_slot(1, &sc);
  std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
  slot_cache->get_slot(2, &sc);
  std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;

  delete slot_cache;

  slot_cache = new SlotCache("test_slotpage");

  slot_cache->get_slot(0, &sc);
  std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
  slot_cache->get_slot(1, &sc);
  std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;
  slot_cache->get_slot(2, &sc);
  std::cout << sc.vlog_num << " | " << sc.value_offset << std::endl;

  delete slot_cache;

  return 0;
}



int main() {
  test4();
}