/*
 *  Copyright (C) GridGain Systems. All Rights Reserved.
 *  _________        _____ __________________        _____
 *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
 *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
 *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
 *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
 */

#pragma once

#include <ignite/client/table/ignite_tuple.h>
#include <ignite/client/type_mapping.h>

#include <ignite/common/big_decimal.h>
#include <ignite/common/ignite_date.h>
#include <ignite/common/ignite_date_time.h>
#include <ignite/common/ignite_time.h>
#include <ignite/common/ignite_timestamp.h>
#include <ignite/common/uuid.h>

#include <cstdint>
#include <string>

/**
 * All columns type table mapping (@see ignite_runner_suite::TABLE_NAME_ALL_COLUMNS).
 */
struct all_fields_type {
    all_fields_type() = default;

    explicit all_fields_type(std::int64_t key)
        : m_key(key) {}

    std::int64_t m_key{0};
    std::string m_str;
    std::int8_t m_int8{0};
    std::int16_t m_int16{0};
    std::int32_t m_int32{0};
    std::int64_t m_int64{0};
    float m_float{.0f};
    double m_double{.0};
    ignite::uuid m_uuid;
    ignite::ignite_date m_date;
    ignite::ignite_time m_time;
    ignite::ignite_time m_time2;
    ignite::ignite_date_time m_datetime;
    ignite::ignite_date_time m_datetime2;
    ignite::ignite_timestamp m_timestamp;
    ignite::ignite_timestamp m_timestamp2;
    std::vector<std::byte> m_blob;
    ignite::big_decimal m_decimal;
    bool m_boolean{false};
};

namespace ignite {

template<>
inline ignite_tuple convert_to_tuple(all_fields_type &&value) {
    ignite_tuple tuple;

    tuple.set("key", value.m_key);
    tuple.set("str", value.m_str);
    tuple.set("int8", value.m_int8);
    tuple.set("int16", value.m_int16);
    tuple.set("int32", value.m_int32);
    tuple.set("int64", value.m_int64);
    tuple.set("float", value.m_float);
    tuple.set("double", value.m_double);
    tuple.set("uuid", value.m_uuid);
    tuple.set("date", value.m_date);
    tuple.set("time", value.m_time);
    tuple.set("time2", value.m_time2);
    tuple.set("datetime", value.m_datetime);
    tuple.set("datetime2", value.m_datetime2);
    tuple.set("timestamp", value.m_timestamp);
    tuple.set("timestamp2", value.m_timestamp2);
    tuple.set("blob", value.m_blob);
    tuple.set("decimal", value.m_decimal);
    tuple.set("boolean", value.m_boolean);

    return tuple;
}

template<>
inline all_fields_type convert_from_tuple(ignite_tuple &&value) {
    all_fields_type res;

    res.m_key = value.get<std::int64_t>("key");

    if (value.column_count() > 1) {
        res.m_str = value.get<std::string>("str");
        res.m_int8 = value.get<std::int8_t>("int8");
        res.m_int16 = value.get<std::int16_t>("int16");
        res.m_int32 = value.get<std::int32_t>("int32");
        res.m_int64 = value.get<std::int64_t>("int64");
        res.m_float = value.get<float>("float");
        res.m_double = value.get<double>("double");
        res.m_uuid = value.get<uuid>("uuid");
        res.m_date = value.get<ignite_date>("date");
        res.m_time = value.get<ignite_time>("time");
        res.m_time2 = value.get<ignite_time>("time2");
        res.m_datetime = value.get<ignite_date_time>("datetime");
        res.m_datetime2 = value.get<ignite_date_time>("datetime2");
        res.m_timestamp = value.get<ignite_timestamp>("timestamp");
        res.m_timestamp2 = value.get<ignite_timestamp>("timestamp2");
        res.m_blob = value.get<std::vector<std::byte>>("blob");
        res.m_decimal = value.get<big_decimal>("decimal");
        res.m_boolean = value.get<bool>("boolean");
    }

    return res;
}

} // namespace ignite
