/*
   Copyright 2023-2024  Leil Storage OÜ

   This file is part of SaunaFS.

   SaunaFS is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, version 3.

   SaunaFS 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with SaunaFS. If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "common/platform.h"

#include <ctime>
#include <filesystem>
#include <mutex>
#include <string>

class IChunkTrashManagerImpl {
public:
	virtual ~IChunkTrashManagerImpl() = default;

	virtual int moveToTrash(const std::filesystem::path &, const std::filesystem::path &,
	                        const std::time_t &) = 0;

	virtual int init(const std::string &) = 0;

	virtual void collectGarbage() = 0;

	virtual void reloadConfig() = 0;
};

/**
 * @brief Manages the trash files in the system.
 *
 * This class provides functionality to initialize the trash, move files to the
 * trash, and manage expired files.
 */
class ChunkTrashManager {
public:
	using Implementation = IChunkTrashManagerImpl;
	using ImplementationPtr = std::shared_ptr<Implementation>;

	/**
	 * @brief Sets the implementation for the ChunkTrashManager.
	 *
	 * @param newImpl The new implementation to be set.
	 */
	static void setImpl(ImplementationPtr newImpl);

	/**
	 * @brief The name of the trash directory.
	 */
	static inline const std::string kTrashDirname = ".trash.bin";

	static u_short isEnabled;  ///< Flag to enable or disable the trash manager.

	/**
	 * @brief Initializes the trash directory for the specified disk.
	 *
	 * @param diskPath The path of the disk where the trash directory will be
	 * initialized.
	 * @return Status code indicating success or failure.
	 */
	static int init(const std::string &diskPath);

	/**
	 * @brief Moves a file to the trash directory.
	 *
	 * @param filePath The path of the file to be moved.
	 * @param diskPath The path to the disk containing the file.
	 * @param deletionTime The time when the file was deleted.
	 * @return 0 on success, error code otherwise.
	 */
	static int moveToTrash(const std::filesystem::path &filePath,
	                       const std::filesystem::path &diskPath, const std::time_t &deletionTime);

	/**
	 * @brief Runs the garbage collection process, which includes
	 * removing expired files, freeing up disk space, and cleaning
	 * empty directories.
	 */
	static void collectGarbage();

	/// Reloads the configuration for the trash manager.
	static void reloadConfig();

	// Deleted to enforce singleton behavior.
	// It follows the Static Class with Encapsulated State pattern, ensuring
	// a single, globally accessible instance of the pImpl implementation
	// without requiring instance management. All methods and members are
	// static, and instantiation is prevented by deleting the constructor. This
	// approach avoids unnecessary singleton complexity while maintaining
	// encapsulation and controlled access to internal state.
	ChunkTrashManager() = delete;
	ChunkTrashManager(const ChunkTrashManager &) = delete;
	ChunkTrashManager &operator=(const ChunkTrashManager &) = delete;
	ChunkTrashManager(ChunkTrashManager &&) = delete;
	ChunkTrashManager &operator=(ChunkTrashManager &&) = delete;

	~ChunkTrashManager() = default;  ///< Destructor

private:
	/// Get the implementation singleton instance using Meyer's singleton
	/// pattern for thread-safety
	static ImplementationPtr &getImpl();

	/// Mutex to protect concurrent access to the implementation singleton
	static std::mutex implMutex;
};
