#include "logger.h"

#include <algorithm>
#include <iostream>

namespace dofs {

Logger::Logger(std::string_view path, bool append) noexcept
        : _path(path) {
        const std::ios::openmode mode = append ? std::ios::app : std::ios::trunc;
        (void)open(mode);
}

bool Logger::open(std::ios::openmode mode) noexcept {
        _stream.exceptions(std::ios::goodbit);
        _stream.open(_path, std::ios::out | mode);
        _is_open = _stream.is_open();

        if (!_is_open) {
                DOFS_ERROR("Logger", ("failed to open file: " + _path).c_str());
        }

        return _is_open;
}

Logger::~Logger() noexcept {
        close();
}

void Logger::flush() noexcept {
        std::lock_guard<std::mutex> _lk(_mutex);

        if (_is_open) {
                _stream.flush();

                if (!_stream) {
                        DOFS_ERROR("Logger", ("flush failed for: " + _path).c_str());
                }
        }
}

void Logger::close() noexcept {
        std::lock_guard<std::mutex> _lk(_mutex);

        if (_is_open) {
                _stream.flush();
                _stream.close();
                _is_open = false;
        }
}

void Logger::write_line(std::string_view line) noexcept {
        std::lock_guard<std::mutex> _lk(_mutex);

        if (!_is_open) {
                DOFS_ERROR("Logger", ("write on closed file: " + _path).c_str());
                return;
        }

        _stream << line << '\n';

        if (!_stream) {
                DOFS_ERROR("Logger", ("write failed for: " + _path).c_str());
        }
}

} // namespace dofs
