/*
 * SPDX-FileCopyrightText: 2014 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

#include <tango/client/DevicePipe.h>

#include <tango/client/ApiExcept.h>
#include <tango/common/utils/assert.h>
#include <tango/server/Except.h>
#include <tango/server/seq_vec.h>
#include <tango/server/tango_clock.h>

#include <algorithm>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>

using namespace CORBA;

namespace Tango
{

//------------------------------------------------------------------------------------------------------------------
//
// method:
//         DevicePipe::DevicePipe()
//
// description:
//        Constructor for DevicePipe class
//
//------------------------------------------------------------------------------------------------------------------

DevicePipe::DevicePipe() :
    ext(nullptr)
{
}

DevicePipe::DevicePipe(const std::string &pipe_name) :
    name(pipe_name),
    ext(nullptr)
{
}

DevicePipe::DevicePipe(const std::string &pipe_name, const std::string &root_blob_name) :
    name(pipe_name),
    ext(nullptr)
{
    the_root_blob.set_name(root_blob_name);
}

//-----------------------------------------------------------------------------
//
// DevicePipe::DevicePipe() - copy constructor to create DevicePipe
//
//-----------------------------------------------------------------------------

DevicePipe::DevicePipe(const DevicePipe &source) :
    ext(nullptr)
{
    name = source.name;
    time = source.time;
    the_root_blob = source.the_root_blob;

    if(source.ext != nullptr)
    {
        ext = std::make_unique<DevicePipeExt>();
        *(ext) = *(source.ext);
    }
}

//-----------------------------------------------------------------------------
//
// DevicePipe::operator= - assignment operator for DevicePipe class
//
//-----------------------------------------------------------------------------

DevicePipe &DevicePipe::operator=(const DevicePipe &rhs)
{
    if(this != &rhs)
    {
        name = rhs.name;
        time = rhs.time;
        the_root_blob = rhs.the_root_blob;

        if(rhs.ext != nullptr)
        {
            ext = std::make_unique<DevicePipeExt>();
            *(ext) = *(rhs.ext);
        }
    }
    return *this;
}

//-----------------------------------------------------------------------------
//
// DevicePipe::DevicePipe() - Move copy constructor to create DevicePipe
//
//-----------------------------------------------------------------------------

DevicePipe::DevicePipe(DevicePipe &&source) :
    ext(nullptr)
{
    name = std::move(source.name);
    time = source.time;
    the_root_blob = std::move(source.the_root_blob);

    if(source.ext != nullptr)
    {
        ext = std::move(source.ext);
    }
}

//-----------------------------------------------------------------------------
//
// DevicePipe::operator= - Move assignment operator for DevicePipe class
//
//-----------------------------------------------------------------------------

DevicePipe &DevicePipe::operator=(DevicePipe &&rhs)
{
    name = std::move(rhs.name);
    time = rhs.time;
    the_root_blob = std::move(rhs.the_root_blob);

    if(rhs.ext != nullptr)
    {
        ext = std::move(rhs.ext);
    }
    else
    {
        ext.reset();
    }

    return *this;
}

//----------------------------------------------------------------------------------------------------------------
//
// DevicePipe::~DevicePipe() - destructor to destroy DevicePipe
//
//----------------------------------------------------------------------------------------------------------------

DevicePipe::~DevicePipe() { }

DevicePipe &DevicePipe::operator[](const std::string &_na)
{
    the_root_blob.operator[](_na);
    return *this;
}

//+------------------------------------------------------------------------------------------------------------------
//
// Function
//         operator overloading :     <<
//
// description :
//        Friend function to ease printing instance of the DevicePipe class
//
//-------------------------------------------------------------------------------------------------------------------

std::ostream &operator<<(std::ostream &o_str, const DevicePipe &dd)
{
    //
    // Pipe date
    //

    if(dd.time.tv_sec != 0)
    {
        std::tm tm = Tango_localtime(dd.time.tv_sec);
        o_str << std::put_time(&tm, "%c") << " (" << dd.time.tv_sec << "," << dd.time.tv_usec << " sec) : ";
    }

    //
    // Print pipe name
    //

    o_str << dd.name << std::endl;

    //
    // Print blob
    //

    const DevicePipeBlob &dpb = dd.get_root_blob();
    if(dpb.get_insert_data() == nullptr && dpb.get_extract_data() == nullptr)
    {
        o_str << "DevicePipe is empty";
    }
    else
    {
        dpb.print(o_str, 0, true);
        dpb.print(o_str, 0, false);
    }

    return o_str;
}

DevicePipe &operator>>(DevicePipe &_dp, char *&datum)
{
    _dp.get_root_blob().operator>>(datum);
    return _dp;
}

} // namespace Tango
