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

#ifndef TANGO_CLIENT_DBSERVERDATA_H
#define TANGO_CLIENT_DBSERVERDATA_H

#include <tango/client/DeviceProxy.h>

#include <string>
#include <vector>

/** @defgroup DBase Database Client classes
 * @ingroup Client
 */

namespace Tango
{
class Database;

/****************************************************************************************
 *                                                                                         *
 *                     The DbServerData class                                                *
 *                     ----------------                                                    *
 *                                                                                         *
 ***************************************************************************************/

//
// DbServerData object to implement the features required to move a complete device server proces
// configuration from one database to another one
//

/**
 * Class used to move/copy a complete device server process database configuration
 * from one Tango host to another
 *
 * @headerfile tango.h
 * @ingroup DBase
 */
class DbServerData
{
  private:
    struct TangoProperty
    {
        std::string name;
        std::vector<std::string> values;

        TangoProperty(std::string &na, std::vector<std::string> &val) :
            name(na),
            values(val)
        {
        }
    };

    struct TangoAttribute : std::vector<TangoProperty>
    {
        std::string name;

        TangoAttribute(std::string na) :
            name(na)
        {
        }
    };

    struct TangoPipe : std::vector<TangoProperty>
    {
        std::string name;

        TangoPipe(std::string na) :
            name(na)
        {
        }
    };

    struct TangoDevice : DeviceProxy
    {
        std::string name;
        std::vector<TangoProperty> properties;
        std::vector<TangoAttribute> attributes;
        std::vector<TangoPipe> pipes;

        TangoDevice(const std::string &);

        std::string get_name()
        {
            return name;
        }

        std::vector<TangoProperty> &get_properties()
        {
            return properties;
        }

        std::vector<TangoAttribute> &get_attributes()
        {
            return attributes;
        }

        std::vector<TangoPipe> &get_pipes()
        {
            return pipes;
        }

        void put_properties(Database *);
        void put_attribute_properties(Database *);
        void put_pipe_properties(Database *);
    };

    struct TangoClass : std::vector<TangoDevice>
    {
        std::string name;
        std::vector<TangoProperty> properties;
        std::vector<TangoAttribute> attributes;
        std::vector<TangoPipe> pipes;

        TangoClass(const std::string &, const std::string &, Database *);

        std::string get_name()
        {
            return name;
        }

        std::vector<TangoProperty> &get_properties()
        {
            return properties;
        }

        std::vector<TangoAttribute> &get_attributes()
        {
            return attributes;
        }

        std::vector<TangoPipe> &get_pipes()
        {
            return pipes;
        }

        void put_properties(Database *);
        void put_attribute_properties(Database *);
        void put_pipe_properties(Database *);
        void remove_properties(Database *);
    };

    void create_server(Database *);
    void put_properties(Database *);

    std::string full_server_name;
    std::vector<TangoClass> classes;

  public:
    /**
     * Create a DbServerData instance.
     *
     * A constructor for a DbServerData object for a device server process defined in the TANGO database specified by
     * the TANGO_HOST environment variable
     *
     * @param [in] ds_exec_name    The device server process executable name
     * @param [in] ds_inst_name The device server process instance name
     *
     */
    DbServerData(const std::string &ds_exec_name, const std::string &ds_inst_name);
    /**
     * Check if device(s) already defined
     *
     * Return true if one of the device defined in the device server process with configuration in this instance is
     * already defined in the database defined by the Tango host given as parameter
     *
     * @param [in] tg_host The tango host
     * @return Boolean set to true if one of the device server device is defined in the Tango host given as parameter
     */
    bool already_exist(const std::string &tg_host);
    /**
     * Put device server database configuration in new Tango host
     *
     * Store the device server process database configuration in the database specified by the given Tango host
     * parameter
     *
     * @param [in] tg_host The tango host
     */
    void put_in_database(const std::string &tg_host);
    /**
     * Remove device server database configuration from Tango host
     *
     * Remove the device server process database configuration from the database specified by the given Tango host
     * parameter
     *
     * @param [in] tg_host The tango host
     */
    void remove(const std::string &tg_host);
    /**
     * Remove device server database configuration from default Tango host
     *
     * Remove the device server process database configuration from the database specified by the environment variable
     * TANGO_HOST
     *
     */
    void remove();

    ///@privatesection
    ~DbServerData() { }

    const std::string &get_name()
    {
        return full_server_name;
    }

    std::vector<TangoClass> &get_classes()
    {
        return classes;
    }
};
} // namespace Tango

#endif // TANGO_CLIENT_DBSERVERDATA_H
