#ifndef CPU_KNAPSACK_DATA_HPP
#define CPU_KNAPSACK_DATA_HPP

#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <cstdint>

struct Item
{
	std::uint32_t size;
	std::uint32_t priority;
};

using items_t = std::vector<Item>;
using selection_t = std::uint64_t;
using result_t = std::vector<selection_t>;

/**
 * Converts the selection bitmask to a string of 0s and 1s, where '1' at position i means that item i is selected.
 */
std::string selection2str(selection_t selection, std::size_t items)
{
	std::stringstream ss;
	for (std::size_t i = 0; i < items; ++i) {
		ss << ((selection >> i) & 1);
	}
	return ss.str();
}

/**
 * Load a text file containing the items, where each item is represented by two numbers in decimal format on single line,
 * the firest number is the size of the item, and the second number is the priority of the item. The numbers are separated by a space.
 */
void loadItems(const std::string& filename, items_t& items)
{
	std::ifstream file(filename);
	if (!file.is_open()) {
		throw std::runtime_error("Could not open file: " + filename);
	}

	items.clear();
	while (file) {
		std::string line;
		std::getline(file, line);
		if (line.empty()) {
			continue;
		}
		std::istringstream iss(line);
		Item item;
		if (!(iss >> item.size >> item.priority)) {
			throw std::runtime_error("Invalid line format: " + line);
		}
		items.push_back(item);
	}
}

/**
 * Save results in a text file. The fist line is one number -- the sum of priorities of the given results.
 * The remaining lines are selections represented as strings of 0s and 1s, where '1' at position i means that item i is selected.
 * All presented selections have the same sum of priorities and are within specified size limits.
 */
void saveResults(const result_t& results, std::uint64_t priority, std::size_t items, const std::string& filename)
{
	std::ofstream file(filename);
	if (!file.is_open()) {
		throw std::runtime_error("Could not open file: " + filename);
	}

	file << priority << std::endl;
	for (const auto& selection : results) {
		file << selection2str(selection, items) << std::endl;
	}
}

#endif