/*
 * Copyright (c) Atmosphère-NX
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 this program.  If not, see .
 */
#include 
namespace ams::fs {
    namespace {
        constinit bool g_auto_abort_enabled = true;
        /* NOTE: This generates a global constructor. */
        os::SdkThreadLocalStorage g_context_tls;
    }
    void SetEnabledAutoAbort(bool enabled) {
        g_auto_abort_enabled = enabled;
    }
    AbortSpecifier DefaultResultHandler(Result result) {
        AMS_UNUSED(result);
        if (g_auto_abort_enabled) {
            return AbortSpecifier::Default;
        } else {
            return AbortSpecifier::Return;
        }
    }
    AbortSpecifier AlwaysReturnResultHandler(Result result) {
        AMS_UNUSED(result);
        return AbortSpecifier::Return;
    }
    constinit FsContext g_default_context(DefaultResultHandler);
    constinit FsContext g_always_return_context(AlwaysReturnResultHandler);
    void SetDefaultFsContextResultHandler(const ResultHandler handler) {
        if (handler == nullptr) {
            g_default_context.SetHandler(DefaultResultHandler);
        } else {
            g_default_context.SetHandler(handler);
        }
    }
    const FsContext *GetCurrentThreadFsContext() {
        const FsContext *context = reinterpret_cast(g_context_tls.GetValue());
        if (context == nullptr) {
            context = std::addressof(g_default_context);
        }
        return context;
    }
    void SetCurrentThreadFsContext(const FsContext *context) {
        g_context_tls.SetValue(reinterpret_cast(context));
    }
    ScopedAutoAbortDisabler::ScopedAutoAbortDisabler() : m_prev_context(GetCurrentThreadFsContext()) {
        SetCurrentThreadFsContext(std::addressof(g_always_return_context));
    }
}