/*
 * SPDX-FileCopyrightText: 2011 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */
// NOLINTBEGIN(*)

#ifdef WIN32
  #include <process.h>
#else
  #include <unistd.h>
#endif

#include "old_common.h"

int main(int argc, char **argv)
{
    AttributeProxy *attr;

    if(argc != 2)
    {
        TEST_LOG << "usage: " << argv[0] << " <attribute>" << endl;
        exit(-1);
    }

    string attribute_name = argv[1];

    try
    {
        attr = new AttributeProxy(attribute_name);
    }
    catch(CORBA::Exception &e)
    {
        Except::print_exception(e);
        exit(1);
    }

    TEST_LOG << '\n' << "new AttributeProxy returned" << '\n' << endl;

    int elapsed;
    try
    {
        // Test ping

        elapsed = attr->ping();

        TEST_LOG << "   Ping ( " << elapsed << " us ) --> OK" << endl;

        // Test state

        DevState sta;
        sta = attr->state();

        assert(sta == Tango::ON);
        TEST_LOG << "   State --> OK" << endl;

        // Test status

        string str;
        str = attr->status();

        assert(str == "The device is in ON state.");
        TEST_LOG << "   Status --> OK" << endl;

        // Test name

        string name;
        name = attr->name();

        assert(name == "Short_attr_rw");
        TEST_LOG << "   Name --> OK" << endl;

        // Test get_attribute_config

        AttributeInfo attr_conf;

        attr_conf = attr->get_config();

        assert(attr_conf.name == "Short_attr_rw");
        assert(attr_conf.data_format == SCALAR);
        assert(attr_conf.data_type == DEV_SHORT);

        AttributeInfoEx attr_conf_ex;

        attr_conf_ex = attr->get_config();

        assert(attr_conf_ex.name == "Short_attr_rw");
        assert(attr_conf_ex.data_format == SCALAR);
        assert(attr_conf_ex.data_type == DEV_SHORT);
        assert(attr_conf_ex.alarms.min_alarm == "Not specified");
        assert(attr_conf_ex.alarms.delta_t == "Not specified");
        assert(attr_conf_ex.events.ch_event.abs_change == "Not specified");

        TEST_LOG << "   Get config --> OK" << endl;

        // Test set_attribute_config

        AttributeInfo co = attr->get_config();

#ifdef WIN32
        int pid = _getpid();
#else
        pid_t pid = getpid();
#endif

        stringstream st;

        string s;
        st << pid;
        st >> s;

        co.format = s;

        attr->set_config(co);

        AttributeInfo res = attr->get_config();
        assert(res.format == s);

        AttributeInfoEx co_ex = attr->get_config();
        co_ex.display_unit = s;

        attr->set_config(co_ex);

        AttributeInfoEx res_ex = attr->get_config();
        assert(res_ex.display_unit == s);

        TEST_LOG << "   Set config --> OK" << endl;

        res_ex.format = "Not specified";
        res_ex.display_unit = "Not specified";
        attr->set_config(res_ex);

        // Test read

        DeviceAttribute da;
        da = attr->read();
        short val;
        da >> val;
        assert(val == 66);

        TEST_LOG << "   Read --> OK" << endl;

        // Test write

        val = 88;
        da << val;
        attr->write(da);

        DeviceAttribute da_res;
        da_res = attr->read();
        short val_res;
        da_res >> val_res;

        assert(val_res == 88);

        TEST_LOG << "   Write --> OK" << endl;

        val = 66;
        da << val;
        attr->write(da);

        // Test poll method

        bool pol = attr->is_polled();
        assert(pol == false);

        attr->poll(1000);

        pol = attr->is_polled();
        assert(pol == true);

        TEST_LOG << "   poll --> OK" << endl;

        // Test get_poll_period

        int pol_per = attr->get_poll_period();
        assert(pol_per == 1000);

        TEST_LOG << "   get_poll_period --> OK" << endl;

        // Test history

        std::this_thread::sleep_for(std::chrono::seconds(3));
        vector<DeviceAttributeHistory> *hist = attr->history(2);

        int i;
        for(i = 0; i < 2; i++)
        {
            assert((*hist)[i].get_name() == "Short_attr_rw");
            assert((*hist)[i].has_failed() == false);
            val = 0;
            (*hist)[i] >> val;
            assert(val == 66);
        }

        TEST_LOG << "   history --> OK" << endl;

        delete hist;

        //  Test stop_poll

        attr->stop_poll();
        pol = attr->is_polled();
        assert(pol == false);

        TEST_LOG << "   stop_poll --> OK" << endl;

        // Test read_asynch and read_reply

        long id = attr->read_asynch();
        std::this_thread::sleep_for(std::chrono::seconds(1));
        DeviceAttribute *da_ptr = attr->read_reply(id);
        val = 0;
        (*da_ptr) >> val;
        assert(val == 66);

        TEST_LOG << "   read_asynch() and read_reply() --> OK" << endl;
        delete da_ptr;

        // Test write_asynch and write_reply

        val = 99;
        da << val;
        id = attr->write_asynch(da);
        std::this_thread::sleep_for(std::chrono::seconds(1));
        attr->write_reply(id);
        da_res = attr->read();
        val = 0;
        da_res >> val_res;
        assert(val_res == 99);

        val = 66;
        da << val;
        attr->write(da);

        TEST_LOG << "   write_asynch() and write_reply() --> OK" << endl;

        // Test put property

        DbDatum dd("tst_prop");
        long lg = 1234;
        dd << lg;
        DbData in_prop;
        in_prop.push_back(dd);

        attr->put_property(in_prop);

        // Test get property

        string prop_name("tst_prop");
        DbData out_prop;

        attr->get_property(prop_name, out_prop);

        long lg_res = 0;
        out_prop[0] >> lg_res;

        assert(lg_res == 1234);
        TEST_LOG << "   put_property() and get_property() --> OK" << endl;

        // Test delete property

        attr->delete_property(prop_name);

        DbData no_prop;
        attr->get_property(prop_name, no_prop);
        assert(no_prop[0].is_empty() == true);

        TEST_LOG << "   delete_property() --> OK" << endl;

        // Test multiple get_property

        DbDatum dd_1("tst_prop_1");
        DbDatum dd_2("tst_prop_2");
        long lg_i = 3333;
        dd_1 << lg_i;
        lg_i = 4444;
        dd_2 << lg_i;
        DbData in_prop_m;
        in_prop_m.push_back(dd_1);
        in_prop_m.push_back(dd_2);

        attr->put_property(in_prop_m);

        vector<string> name_list;
        name_list.push_back("tst_prop_1");
        name_list.push_back("tst_prop_10");
        name_list.push_back("tst_prop_2");
        DbData out_prop_m;

        attr->get_property(name_list, out_prop_m);

        long lg_res_2 = 0;
        long lg_res_1 = 0;
        out_prop_m[0] >> lg_res_1;
        out_prop_m[2] >> lg_res_2;

        assert(lg_res_1 == 3333);
        assert(lg_res_2 == 4444);
        assert(out_prop_m[1].is_empty() == true);

        DbData db_dat;
        db_dat.push_back(DbDatum("no"));
        db_dat.push_back(DbDatum("tst_prop_2"));
        db_dat.push_back(DbDatum("yes"));

        attr->get_property(db_dat);

        long lg_3;
        db_dat[1] >> lg_3;

        assert(db_dat[0].is_empty() == true);
        assert(db_dat[2].is_empty() == true);
        assert(lg_3 == 4444);

        TEST_LOG << "   get_property() for multiple properties --> OK" << endl;

        // Test deleting multiple properties

        vector<string> p_name;
        p_name.push_back("tst_prop_1");
        p_name.push_back("tst_prop_2");

        attr->delete_property(p_name);

        DbData no_prop_bis;
        attr->get_property(p_name, no_prop_bis);
        assert(no_prop_bis[0].is_empty() == true);
        assert(no_prop_bis[1].is_empty() == true);

        TEST_LOG << "   delete_property() for multiple properties --> OK" << endl;
    }
    catch(Tango::DevFailed &e)
    {
        Except::print_exception(e);
        exit(-1);
    }

    delete attr;

    return 0;
}

// NOLINTEND(*)
