// vst_entry.cpp — the VST3 module class factory (Phase S1). Enumerates the one class
// this module offers (the ReaSampler instrument) via the SDK's factory macros. The
// Windows module exports — GetPluginFactory (here, via BEGIN_FACTORY) and
// InitDll/ExitDll (from the SDK's dllmain.cpp) — are how REAPER discovers and loads a
// VST3.
//
// VERIFIED (corrects §1a's "experienced estimate" flags on export names + macros,
// against vendor/vst3sdk/public.sdk/source/main/):
//   * Windows exports: InitDll / ExitDll (SMTG_EXPORT_SYMBOL, in dllmain.cpp) +
//     GetPluginFactory (SMTG_EXPORT_SYMBOL IPluginFactory* PLUGIN_API, emitted by the
//     BEGIN_FACTORY macro). The plug-in must provide InitModule/DeinitModule — supplied
//     here by linking moduleinit.cpp (the SDK's default one-time init/term).
//   * Factory macros: BEGIN_FACTORY(vendor,url,email,flags) / DEF_CLASS2(...) /
//     END_FACTORY — exact spellings from pluginfactory.h.
//   * Instrument subcategory string: "Instrument|Synth|Sampler"
//     (PlugType::kInstrumentSynthSampler, ivstaudioprocessor.h).
//   * classFlags = 0 for a SingleComponentEffect (non-distributable), matching the
//     AGain example.

#include "public.sdk/source/main/pluginfactory.h"

#include "pluginterfaces/vst/ivstaudioprocessor.h"  // kVstAudioEffectClass, PlugType

#include "app_version.h"       // vstPluginName / appVersion — the channel-derived identity
#include "ext_keys.h"          // kProjExtNamespace — the pairing-surface assertion target
#include "reasampler_processor.h"
#include "reasampler_vst.h"    // channel-selected class UID (REASAMPLER_ACTIVE_UID_*)

// CHANNEL PAIRING INVARIANT (S18). The instrument's PLUGIN identity forks by the ONE channel
// bit (REASAMPLER_CHANNEL_IS_BETA — the class UID selected in reasampler_vst.h, the filename
// + display name in app_version). Its DATA identity forks by the SAME bit, one layer down:
// ext_keys.h's kProjExtNamespace() delegates to app_version::extStateNamespace(), so a beta
// binary reads "reasampler_beta". Both derive from that one bit, so a beta VST can only ever
// talk to the beta extension.
//
// The guard below pins the two forks together so a refactor cannot split them. It asserts
// that the CLASS UID this factory registers (REASAMPLER_ACTIVE_UID_1, selected by the #if in
// reasampler_vst.h) is the UID that matches THIS binary's channel bit. If someone edited that
// #if to pick the wrong branch — registering the stable UID in a beta build, or vice versa —
// the instrument's identity would diverge from the namespace ext_keys reads (a beta-named
// plugin presenting the stable UID, or reading the stable banks under a beta identity). That
// is exactly the silent split the invariant forbids, and it breaks the build here instead.
// (The namespace itself is a runtime accessor — .c_str() on a channel-selected string — so
// the couplable compile-time fact is the UID selection, not the namespace value; the
// app_version_tests pin the namespace string per channel.)
#if REASAMPLER_CHANNEL_IS_BETA
static_assert(REASAMPLER_ACTIVE_UID_1 == REASAMPLER_PROC_UID_BETA_1 &&
              REASAMPLER_ACTIVE_UID_2 == REASAMPLER_PROC_UID_BETA_2 &&
              REASAMPLER_ACTIVE_UID_3 == REASAMPLER_PROC_UID_BETA_3 &&
              REASAMPLER_ACTIVE_UID_4 == REASAMPLER_PROC_UID_BETA_4,
              "S18: a beta build must register the BETA class UID that pairs with the beta "
              "extension's ext-state namespace — the UID selection and the channel bit split");
#else
static_assert(REASAMPLER_ACTIVE_UID_1 == REASAMPLER_PROC_UID_1 &&
              REASAMPLER_ACTIVE_UID_2 == REASAMPLER_PROC_UID_2 &&
              REASAMPLER_ACTIVE_UID_3 == REASAMPLER_PROC_UID_3 &&
              REASAMPLER_ACTIVE_UID_4 == REASAMPLER_PROC_UID_4,
              "S18: a stable build must register the STABLE class UID that pairs with the "
              "stable ext-state namespace — the UID selection and the channel bit split");
#endif

BEGIN_FACTORY(reasampler::vst::kVendorName, reasampler::vst::kVendorUrl,
              reasampler::vst::kVendorEmail, Steinberg::PFactoryInfo::kNoFlags)

// The display name and version are channel-derived from app_version — sourced here, not
// as literals. DEF_CLASS2 expands inside GetPluginFactory() and PClassInfo2's constructor
// copies the char* into its own fixed buffer at that runtime call, so .c_str() on the
// accessors' static-storage strings is valid (no dangling — the refs outlive the copy).
// vstPluginName(): "ReaSampler 9000" / "ReaSampler 9000 beta". appVersion(): "0.9.01" /
// "0.9.01-beta" (the -beta render V4 already yields on beta).
DEF_CLASS2(INLINE_UID(REASAMPLER_ACTIVE_UID_1, REASAMPLER_ACTIVE_UID_2,
                      REASAMPLER_ACTIVE_UID_3, REASAMPLER_ACTIVE_UID_4),
           Steinberg::PClassInfo::kManyInstances,       // cardinality
           kVstAudioEffectClass,                        // component category (fixed)
           reasampler::vstPluginName().c_str(),         // plug-in display name (channel-derived)
           0,                                           // single-component => 0
           Steinberg::Vst::PlugType::kInstrumentSynthSampler,  // subcategory
           reasampler::appVersion().c_str(),            // plug-in version (channel: -beta render)
           kVstVersionString,                           // VST3 SDK version (fixed)
           reasampler::vst::ReaSamplerProcessor::createInstance)

END_FACTORY
