#pragma once

#include <unistd.h>

#include <string>
#include <tuple>

#include "aqsi-commons-global.h"

namespace aqsi {
/// Класс занимающийся проверкой того, работает ли в текущий момент ещё один экземпляр приложения
class AQSICOMMONS_EXPORT SingleInstanceApplicationLocker
{
public:
    /// Конструктор класса, занимающегося проверкой того, запущен ли ещё один экземпляр приложения
    [[deprecated]] SingleInstanceApplicationLocker();

    /** Попытка создания файла-индикатора запущенного приложения
    \details Пытается открыть файл-индикатор, ранее созданный другим экземпляром приложения. Если не получается,
    вызывает _tryLock() и возвращает true, иначе считывает записанные данные файл (Имя и идентификатор процесса).
    Вызывает kill(pid, 0). Если сигнал доставлен, то считаем, что с приложением всё ок, иначе вызывает _tryLock() и
    возвращает true. После, считывает из /proc/%pid%/cmdline имя процесса и проверяет совпадает ли записанное имя
    процесса с действительным. Если совпадает, то считает, что экземпляр приложения ещё запущен и  возвращает false,
    иначе вызывает _tryLock() и возвращает true.
    \param [in] indicator_filename Имя файла-индикатора
    \throw std::ios_base::failure При возникновении каких-либо ошибок при записи в файл
           std::bad_alloc Если не удалось выделить память под  m_lockFilePath
    \return Если файл уже создан, процесс с таким pid отвечает и имя процесса совпадает с указанным в файле - то
    false, иначе true
    */
    [[deprecated]] bool tryLockSingleInstanceAppCreation(char const* indicator_filename);

private:
    /** Считывает идентификатор и имя процесса из файла
    \param [in,out] stream Файл, из которого будут прочтены идентификатор и имя процесса
    \throw std::ios_base::failure При возникновении каких-либо ошибок при записи в файл
    \return Кортеж, состоящий из идентификатора и имени процесса
    */
    std::tuple<pid_t, std::string> _procInfo(std::ifstream& stream) const;
    /** Считывает имя процесса
    \param [in] pid Идентификатор процесса
    \throw std::ios_base::failure При возникновении каких-либо ошибок при записи в файл
    \return Имя процесса
    */
    std::string _procName(pid_t pid) const;
    /**  Попытка записать данные процесса в файл
    \details Записывает в файл по пути m_lockFilePath индентификатор и имя текущего процесса
    \throw std::ios_base::failure При возникновении каких-либо ошибок при записи в файл
    */
    void _tryLock() const;

    /// Путь к файлу-индикатору
    std::string m_lockFilePath;
};
}  // namespace aqsi
