/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 */

#ifndef SH4LT_READER_H_
#define SH4LT_READER_H_

#include <memory>
#include <string>

#include "../logger/logger.hpp"
#include "../shtype/shtype.hpp"
#include "../time.hpp"
#include "../utils/safe-bool-idiom.hpp"
#include "./sysv-sem.hpp"
#include "./sysv-shm.hpp"
#include "./unix-socket-client.hpp"

namespace sh4lt {
class Reader : public SafeBoolIdiom {
 public:
  using onData = std::function<void(void*, size_t, const Time::info_t*)>;
  using onServerConnected = std::function<void(const ShType&)>;
  using onServerDisconnected = std::function<void()>;
  Reader(const std::string& path,
         onData cb,
         onServerConnected osc,
         onServerDisconnected osd,
         logger::Logger* log);
  ~Reader() override = default;
  Reader() = delete;
  Reader(Reader&&) = delete;
  Reader(const Reader&) = delete;
  auto operator=(const Reader&) -> Reader& = delete;
  auto operator=(Reader&&) -> Reader& = delete;

 private:
  logger::Logger* log_;
  std::string path_;
  size_t cur_size_{0};  // 0 for unknown
  onData on_data_cb_;
  onServerConnected on_server_connected_cb_;
  onServerDisconnected on_server_disconnected_cb_;
  std::unique_ptr<sysVShm> shm_{nullptr};
  std::unique_ptr<sysVSem> sem_{nullptr};
  UnixSocketProtocol::ClientSide proto_;
  std::unique_ptr<UnixSocketClient> cli_;
  bool is_valid_{false};
  [[nodiscard]] auto is_valid() const -> bool final { return is_valid_; }
  void on_server_connected();
  void on_server_disconnected();
  auto on_buffer(sysVSem* sem, size_t size, const Time::info_t* time) -> bool;
};

}  // namespace sh4lt
#endif
