#include "catch2_common.h"

#include <catch2/matchers/catch_matchers.hpp>

constexpr static CORBA::ULong history_depth = 3u;

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

    ~AttrHistoryDev() override { }

    void init_device() override { }

    void read_attr(Tango::Attribute &) override
    {
        TANGO_THROW_EXCEPTION("Some Error", "Not implemented");
    }

    void fill_history_encoded()
    {
        Tango::AttrHistoryStack<Tango::DevEncoded> ahs;
        ahs.length(history_depth);

        Tango::DevEncoded enc;
        enc.encoded_format = Tango::string_dup("Some value");
        enc.encoded_data.length(2);
        enc.encoded_data[0] = 0x1;
        enc.encoded_data[1] = 0x2;

        auto when = Tango::get_current_system_datetime();
        for(CORBA::ULong k = 0; k < history_depth; k++)
        {
            Tango::TimedAttrData<Tango::DevEncoded> tad(&enc, when);
            ahs.push(tad);
        }

        std::string attr_name = "attr";
        Tango::Util *tg = Tango::Util::instance();
        tg->fill_attr_polling_buffer(this, attr_name, ahs);
    }

    static void attribute_factory(std::vector<Tango::Attr *> &attrs)
    {
        attrs.push_back(new TangoTest::AutoAttr<&AttrHistoryDev::read_attr>("attr", Tango::DEV_ENCODED));
    }

    static void command_factory(std::vector<Tango::Command *> &cmds)
    {
        cmds.push_back(new TangoTest::AutoCommand<&AttrHistoryDev::fill_history_encoded>("fill_history_encoded"));
    }
};

TANGO_TEST_AUTO_DEV_TMPL_INSTANTIATE(AttrHistoryDev, 1)

SCENARIO("Attribute history for DEV_Encoded is not supported for old IDLs")
{
    int idlver = GENERATE(TangoTest::idlversion(1, 3));
    GIVEN("a device proxy to a IDLv" << idlver << " device")
    {
        TangoTest::Context ctx{"attr_history", "AttrHistoryDev", idlver};
        auto device = ctx.get_proxy();
        REQUIRE(idlver == device->get_idl_version());

        THEN("we get an exception when trying to fill the attribute history manually in the DS")
        {
            using namespace Catch::Matchers;
            using namespace TangoTest::Matchers;

            // we basically do not want, that history will be populated by Tango
            REQUIRE_NOTHROW(device->poll_attribute("attr", 0));

            REQUIRE_THROWS_MATCHES(device->command_inout("fill_history_encoded"),
                                   Tango::DevFailed,
                                   FirstErrorMatches(Reason(Tango::API_NotSupportedFeature) &&
                                                     DescriptionMatches(ContainsSubstring(
                                                         "DEV_ENCODED data type is supported starting with IDL V4"))));
        }
    }
}
