/*
 * This file provides some utility functions to convert atc_datatype C enum values to atc::DataType enum values and vice-versa.
 */

#include <map>
#include <cstdint>
#include <stdexcept>

#include "data_type.h"
#include "DataType.hpp"

// Single map that hardcodes the necessary atc_data_type conversions.
static const std::map<atc_data_type, atc::DataType> c_to_cpp_map = {
	{ATC_DATA_TYPE_UINT8, atc::DataType::uint8},
	{ATC_DATA_TYPE_UINT16, atc::DataType::uint16},
	{ATC_DATA_TYPE_UINT32, atc::DataType::uint32},
	{ATC_DATA_TYPE_UINT64, atc::DataType::uint64},
	{ATC_DATA_TYPE_INT8, atc::DataType::int8},
	{ATC_DATA_TYPE_INT16, atc::DataType::int16},
	{ATC_DATA_TYPE_INT32, atc::DataType::int32},
	{ATC_DATA_TYPE_INT64, atc::DataType::int64},
	{ATC_DATA_TYPE_FLOAT32, atc::DataType::float32},
	{ATC_DATA_TYPE_FLOAT64, atc::DataType::float64}
};

// This function automatically inverts the map above, preventing the need of hardcoding each conversion twice.
static std::map<atc::DataType, atc_data_type> create_cpp_to_c_map() {
	std::map<atc::DataType, atc_data_type> inverse_map;
	for (auto it = c_to_cpp_map.begin(); it != c_to_cpp_map.end(); it++)
		inverse_map[it->second] = it->first;
	return inverse_map;
}

// We call the function above only once during initialization and store the result in a variable to prevent recomputation.
static const std::map<atc::DataType, atc_data_type> cpp_to_c_map = create_cpp_to_c_map();

atc::DataType convert_data_type(atc_data_type data_type) {
	if (data_type == ATC_DATA_TYPE_ERROR)
		throw std::invalid_argument("Cannot pass ATC_DATA_TYPE_ERROR as atc_data_type of data set, this value is only used by ATC to report an error when returning a data type from read_data_type.");
	return c_to_cpp_map.at(data_type);
}

atc_data_type convert_data_type(atc::DataType data_type) {
	return cpp_to_c_map.at(data_type);
}
