/*
 * SPDX-FileCopyrightText: 2024 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */
#include "common.h"
#include "utils/utils.h"

#include <tango/tango.h>

#include <catch2/catch_template_test_macros.hpp>

template <class Base>
class EmptyDS : public Base
{
  public:
    using Base::Base;

    void init_device() override { }
};

TANGO_TEST_AUTO_DEV_TMPL_INSTANTIATE(EmptyDS, 1)

SCENARIO("catch2 stringmakers specialications (non-standard)")
{
    int idlver = GENERATE(TangoTest::idlversion(6));
    GIVEN("a DeviceProxy to a simple IDLv" << idlver << " device")
    {
        TangoTest::Context ctx{"stringmakers", "EmptyDS", idlver};
        auto device = ctx.get_proxy();

        REQUIRE(idlver == device->get_idl_version());

        WHEN("we can convert it to a string")
        {
            using namespace Catch::Matchers;

            auto result = Catch::StringMaker<Tango::DeviceProxy>::convert(*device);
            REQUIRE_THAT(result, !IsEmpty());
        }
    }

    GIVEN("a CORBA::Any")
    {
        using namespace Catch::Matchers;
        using namespace TangoTest::Matchers;

        CORBA::Any a;
        a <<= (Tango::DevDouble) 1.0;

        REQUIRE_THAT(a, AnyLikeContains(1.0));
        REQUIRE_THAT(a, AnyLikeMatches(WithinAbs(1.0, 0.0000001)));
    }

    GIVEN("a DeviceData")
    {
        using namespace Catch::Matchers;
        using namespace TangoTest::Matchers;

        Tango::DeviceData a;
        a << (Tango::DevDouble) 1.0;

        REQUIRE_THAT(a, AnyLikeContains(1.0));
        REQUIRE_THAT(a, AnyLikeMatches(WithinAbs(1.0, 0.0000001)));
    }

    GIVEN("a DeviceAttribute")
    {
        using namespace Catch::Matchers;
        using namespace TangoTest::Matchers;

        Tango::DeviceAttribute a;
        a << (Tango::DevDouble) 1.0;

        REQUIRE_THAT(a, AnyLikeContains(1.0));
        REQUIRE_THAT(a, AnyLikeMatches(WithinAbs(1.0, 0.0000001)));
    }

    GIVEN("a DevError")
    {
        using namespace Catch::Matchers;

        Tango::DevError err;
        err.severity = Tango::WARN;

        auto result = Catch::StringMaker<Tango::DevError>::convert(err);
        REQUIRE_THAT(result, !IsEmpty());
    }

    GIVEN("a DevError_var")
    {
        using namespace Catch::Matchers;

        auto err = new Tango::DevError;
        err->severity = Tango::WARN;

        Tango::DevError_var var = err;

        auto result = Catch::StringMaker<Tango::DevError>::convert(var);
        REQUIRE_THAT(result, !IsEmpty());
    }

    GIVEN("a DevErrorList")
    {
        using namespace Catch::Matchers;

        Tango::DevErrorList err_list;
        err_list.length(2);
        err_list[0].severity = Tango::WARN;
        err_list[1].severity = Tango::PANIC;

        auto result = Catch::StringMaker<Tango::DevErrorList>::convert(err_list);
        REQUIRE_THAT(result, !IsEmpty());
    }

    GIVEN("a DevErrorList_var")
    {
        using namespace Catch::Matchers;

        auto err_list = new Tango::DevErrorList;
        err_list->length(1);
        (*err_list)[0].severity = Tango::WARN;

        Tango::DevErrorList_var var = err_list;

        auto result = Catch::StringMaker<Tango::DevErrorList>::convert(var);
        REQUIRE_THAT(result, !IsEmpty());
    }
}

// clang-format off
using PrintableType = std::tuple<
                                 Tango::ArchiveEventInfo,
                                 Tango::AttributeAlarmInfo,
                                 Tango::AttributeEventInfo,
                                 Tango::AttributeInfoEx,
                                 Tango::AttrConfEventData,
                                 Tango::AttrConfEventDataList,
                                 Tango::ChangeEventInfo,
                                 Tango::CommandInfo,
                                 Tango::DataReadyEventData,
                                 Tango::DataReadyEventDataList,
                                 Tango::DevIntrChangeEventData,
                                 Tango::DevIntrChangeEventDataList,
                                 Tango::DeviceAttribute,
                                 Tango::DeviceData,
                                 Tango::DeviceInfo,
                                 Tango::EventData,
                                 Tango::EventDataList,
                                 Tango::FwdAttrConfEventData,
                                 Tango::FwdEventData,
                                 Tango::PeriodicEventInfo,
                                 Tango::PipeEventData,
                                 Tango::PipeEventDataList,
                                 Tango::TimeVal,
                                 TangoTest::AttrReadEventCopyable,
                                 TangoTest::AttrWrittenEventCopyable,
                                 TangoTest::CmdDoneEventCopyable,
                                 // IDL classes
                                 Tango::AttributeDim,
                                 Tango::AttributeValue_5,
                                 Tango::AttributeConfig_5,
                                 Tango::ArchiveEventProp,
                                 Tango::AttributeAlarm,
                                 Tango::ChangeEventProp,
                                 Tango::EventProperties,
                                 Tango::PeriodicEventProp
                                 >;
// clang-format on

TEMPLATE_LIST_TEST_CASE("catch2 stringmakers specialications", "", PrintableType)
{
    auto var = TangoTest::construct_default<TestType>();
    using namespace Catch::Matchers;

    auto result = Catch::StringMaker<TestType>::convert(var);
    REQUIRE_THAT(result, !IsEmpty());
}
