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

#ifndef TANGO_CLIENT_LOCKTHREAD_H
#define TANGO_CLIENT_LOCKTHREAD_H

#include <tango/common/tango_const.h>

#include <chrono>
#include <memory>
#include <optional>
#include <string>
#include <vector>

namespace Tango
{

enum LockCmdType
{
    LOCK_TIME_OUT = 0,
    LOCK_COMMAND
};

using LockClock = std::chrono::steady_clock;

//=============================================================================
//
//            The LockThCmd structure
//
// description :    This structure is used to shared data between the locking
//            thread and the main thread.
//
//=============================================================================

struct LockThCmd
{
    bool cmd_pending;                  // The new command flag
    LockCmdCode cmd_code;              // The command code
    std::string dev_name;              // The device name
    LockClock::duration lock_validity; // The lock validity
    bool suicide;                      // The suicide flag
};

struct LockedDevice
{
    std::string dev_name;         // The locked device name
    LockClock::duration validity; // The locked device validity

    bool operator<(const LockedDevice &arg) const
    {
        return validity < arg.validity;
    }
};

//=============================================================================
//
//            The LockThread class
//
// description :    Class to store all the necessary information for the
//            locking thread. It's run() method is the thread code
//
//=============================================================================

class TangoMonitor;
class DeviceProxy;

// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor)
class LockThread : public omni_thread
{
  public:
    LockThread(LockThCmd &, TangoMonitor &, DeviceProxy *, const std::string &, LockClock::duration);

    void run(void *) override;

    void execute_cmd();
    void one_more_lock();
    void unlock_all_devs();
    void update_th_period();
    void compute_sleep_time(bool);
    LockCmdType get_command();

  protected:
    LockThCmd &shared_cmd;
    TangoMonitor &p_mon;

    LockThCmd local_cmd;
    std::optional<LockClock::duration> sleep;

    std::vector<LockedDevice> locked_devices;
    std::vector<std::string> re_lock_cmd_args;
    LockClock::duration period;
    std::unique_ptr<DeviceProxy> admin_proxy;

    LockClock::time_point next_work;

  private:
    ~LockThread() override = default;
};

} // namespace Tango

#endif /* _LOCKTHREAD_ */
