#include "fs_validations.h"

#include <balancer/kernel/helpers/errors.h>

#include <util/system/file.h>
#include <util/system/fstat.h>
#include <util/folder/dirut.h>

namespace NSrvKernel {

    TError CheckFileReadable(const char* file) {
        try {
            TFile(file, RdOnly);
        } Y_TRY_STORE(TFileError, yexception);
        return {};
    }

    TThreadedFsValidationImpl::TThreadedFsValidationImpl(const TStringBuf name) noexcept
        : Name_(name)
    {}

    void TThreadedFsValidationImpl::DoRun() {
        Y_ASSERT(Action);
        (this->*Action)();
    }

    void TThreadedFsValidationImpl::StatFunction() noexcept {
        Stat_ = TFileStat(Name_, false);
        Action = nullptr;
    }

    void TThreadedFsValidationImpl::FileRealPathFunction() noexcept {
        try {
            FileRealPath_ = RealPath(Name_.c_str());
            Action = nullptr;
        } catch(const TFileError& e) {
            Action = &TThreadedFsValidationImpl::Error;
        }
    }

    TThreadedStat::TThreadedStat(const TString &name, TThreadedQueue *queue) noexcept
        : Impl_(new TImpl(name))
        , Queue_(queue)
    {
        Impl_->Action = &TImpl::StatFunction;
        Impl_ = THolder<TImpl>(Queue_->Run(Impl_.Release(), TInstant::Max()).Release());
    }

    const TFileStat TThreadedStat::Stat() const noexcept {
        if (!Impl_) {
            return TFileStat();
        }

        if (Impl_->Action == &TImpl::Error) {
            return TFileStat();
        }

        return Impl_->Stat();
    }

    TThreadedRealPath::TThreadedRealPath(const TString &name, TThreadedQueue *queue) noexcept
        : Impl_(new TImpl(name))
        , Queue_(queue)
    {
        Impl_->Action = &TImpl::FileRealPathFunction;
        Impl_ = THolder<TImpl>(Queue_->Run(Impl_.Release(), TInstant::Max()).Release());
    }

    TString TThreadedRealPath::FileRealPath() const noexcept {
        if (!Impl_) {
            return {};
        }

        if (Impl_->Action == &TImpl::Error) {
            return {};
        }

        return Impl_->FileRealPath();
    }
}
