#pragma once

#include <saas/library/daemon_base/module/module.h>
#include <saas/rtyserver_jupi/library/extbuilder/assert_policy.h>
#include <util/generic/hash_set.h>
#include <util/string/vector.h>
#include <util/string/join.h>

namespace NFusion {
    class TExtBuilderConfig: public TPluginConfig<IDaemonModuleConfig> {
    public:
        using TDbgFlags = THashSet<TString>;

        enum class EOnFailPolicy {
            Ignore  /* "IGNORE" */, // log and ignore
            Crash   /* "CRASH" */,  // calls Panic
            Stop    /* "STOP" */    // calls AbortFromCorrupedIndex + detects previous crashes
        };

    public:
        inline const TString& GetBundleVersion() const {
            return BundleVersion_;
        }

        inline const TDbgFlags& GetDbgFlags() const {
            return DbgFlags_;
        }

        inline const TString& GetStatePath() const {
            return StatePath_;
        }

        inline const TString& GetModelsPath() const {
            return ModelsPath_;
        }

        inline const TString& GetTimerLogPath() const {
            return TimerLogPath_;
        }

        inline bool GetForceKeepPreparates() const {
            return ForceKeepPreparates_;
        }

        inline bool GetHeavyDataLumpsEnabled() const {
            return HeavyDataLumpsEnabled_;
        }

        TAssertPolicy CreateAssertPolicy() const {
            TAssertPolicy pol;
            pol.CrashOnMergeFail_ = (OnFail_ == EOnFailPolicy::Crash);
            pol.StopOnIncompleteMerge_ = (OnFail_ == EOnFailPolicy::Stop);
            pol.StopAfterIncompleteMerge_ = (OnFail_ != EOnFailPolicy::Ignore) && DbgFlags_.contains("detect_failed_index_by_asserts");
            pol.VerifyBundleDependencies_ = !DbgFlags_.contains("allow_missing_dependencies");
            return pol;
        }
    protected:
        TString TimerLogPath_;
        TString BundleVersion_;
        EOnFailPolicy OnFail_ = EOnFailPolicy::Ignore;
        TDbgFlags DbgFlags_;
        TString StatePath_ = Default<TString>();
        TString ModelsPath_ = Default<TString>();
        bool ForceKeepPreparates_ = false;
        bool HeavyDataLumpsEnabled_;

    protected:
        virtual bool DoCheck() const {
            return true;
        }

        virtual void DoInit(const TYandexConfig::Section& moduleSection) {
            const TYandexConfig::Directives& directives = moduleSection.GetDirectives();
            auto vals = directives.Value("DbgFlags", Default<TString>());

            DbgFlags_.clear();
            auto vec = SplitString(vals, ", ");
            for (const TString& val : vec) {
                DbgFlags_.insert(val);
            }

            TimerLogPath_ = directives.Value("TimerLogPath", Default<TString>());
            BundleVersion_ = directives.Value("BundleVersion", Default<TString>());
            OnFail_ = directives.Value("OnFail", EOnFailPolicy::Ignore);
            StatePath_ = directives.Value("StatePath", Default<TString>());
            ModelsPath_ = directives.Value("ModelsPath", Default<TString>());
            ForceKeepPreparates_ = directives.Value("ForceKeepPreparates", false);
            HeavyDataLumpsEnabled_ = directives.Value("HeavyDataLumpsEnabled", false);
        }

        virtual void DoToString(IOutputStream& so) const {
            so << "BundleVersion : " << BundleVersion_ << Endl;
            so << "OnFail : " << OnFail_ << Endl;
            so << "DbgFlags : " << JoinSeq(", ", DbgFlags_) << Endl;
            so << "StatePath: " << StatePath_ << Endl;
            so << "ModelsPath: " << ModelsPath_ << Endl;
            so << "ForceKeepPreparates: " << ForceKeepPreparates_ << Endl;
            so << "TimerLogPath: " << TimerLogPath_ << Endl;
            so << "HeavyDataLumpsEnabled: " << HeavyDataLumpsEnabled_ << Endl;
        }
    };
}
