#define private public
#include "emc/rs274ngc/rs274ngc_interp.hh"
#undef private

#include <cstdlib>
#include <iostream>

#include "linuxcnc_hal_adapter.hh"

namespace {

void seed_hal_values()
{
    standalone::reset_hal_adapter();

    hal_data_u pin_bit{};
    pin_bit.b = true;
    standalone::set_hal_value(standalone::HalValueKind::Pin, "standalone.pin-bit", HAL_BIT,
                              pin_bit);

    hal_data_u signal_float{};
    signal_float.f = 98.25;
    standalone::set_hal_value(standalone::HalValueKind::Signal, "standalone.signal-float",
                              HAL_FLOAT, signal_float);

    hal_data_u param_s32{};
    param_s32.s = -17;
    standalone::set_hal_value(standalone::HalValueKind::Param, "standalone.param-s32", HAL_S32,
                              param_s32);

    hal_data_u pin_u32{};
    pin_u32.u = 123456789u;
    standalone::set_hal_value(standalone::HalValueKind::Pin, "standalone.pin-u32", HAL_U32,
                              pin_u32);

    hal_data_u signal_s64{};
    signal_s64.ls = -9000000000LL;
    standalone::set_hal_value(standalone::HalValueKind::Signal, "standalone.signal-s64", HAL_S64,
                              signal_s64);

    hal_data_u param_u64{};
    param_u64.lu = 9000000000ULL;
    standalone::set_hal_value(standalone::HalValueKind::Param, "standalone.param-u64", HAL_U64,
                              param_u64);

    hal_data_u disconnected{};
    disconnected.f = 12.5;
    standalone::set_hal_value(standalone::HalValueKind::Pin, "standalone.disconnected-float",
                              HAL_FLOAT, disconnected, false);
}

void print_named_value(Interp &interp, const char *name)
{
    int status = 0;
    double value = 0.0;
    const int rc = interp.find_named_param(name, &status, &value);
    std::cout << name << ": rc=" << rc << " found=" << status << " value=" << value << "\n";
}

}  // namespace

int main(int argc, char **argv)
{
    if (argc == 2) {
        setenv("INI_FILE_NAME", argv[1], 1);
    }

    Interp interp;
    seed_hal_values();
    interp._setup.feature_set = FEATURE_INI_VARS | FEATURE_HAL_PIN_VARS;
    interp._setup.length_units = CANON_UNITS_MM;
    interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
    interp._setup.motion_mode = G_1;
    interp._setup.feed_rate = 123.45;
    interp._setup.speed[0] = 678.9;
    interp._setup.current_x = 1.25;
    interp._setup.current_y = 2.5;
    interp._setup.current_z = 3.75;
    interp._setup.parameters[interp_param_global::TOOL_NUMBER] = 12.0;

    const int rc = interp.init_named_parameters();
    std::cout << "init_named_parameters=" << rc << "\n";
    std::cout << "global_named_count=" << interp._setup.sub_context[0].named_params.size() << "\n";
    std::cout << "required_parameter_first=" << interp_param_global::G28_X << "\n";
    std::cout << "readonly_tool_number_index=" << interp_param_global::TOOL_NUMBER << "\n";

    print_named_value(interp, "_vmajor");
    print_named_value(interp, "_vminor");
    print_named_value(interp, "_metric_machine");
    print_named_value(interp, "_motion_mode");
    print_named_value(interp, "_metric");
    print_named_value(interp, "_feed");
    print_named_value(interp, "_rpm");
    print_named_value(interp, "_x");
    print_named_value(interp, "_current_tool");
    print_named_value(interp, "_ini[traj]max_linear_velocity");
    print_named_value(interp, "_hal[standalone.pin-bit]");
    print_named_value(interp, "_hal[standalone.signal-float]");
    print_named_value(interp, "_hal[standalone.param-s32]");
    print_named_value(interp, "_hal[standalone.pin-u32]");
    print_named_value(interp, "_hal[standalone.signal-s64]");
    print_named_value(interp, "_hal[standalone.param-u64]");
    print_named_value(interp, "_hal[standalone.disconnected-float]");
    print_named_value(interp, "_hal[standalone.missing]");

    return rc == INTERP_OK ? 0 : 1;
}
