pub type ModuleMapEntry = (ModuleInfo, ModuleReference);
#[cosmwasm_schema::cw_serde]
pub struct Config {
    pub allow_direct_module_registration_and_updates: bool,
    pub namespace_registration_fee: cosmwasm_std::Coin,
}
pub mod state {
    use cw_controllers::Admin;
    use cw_storage_plus::{Item, Map};
    use crate::objects::{
        account_id::AccountId,
        common_namespace::ADMIN_NAMESPACE,
        module::{ModuleInfo, ModuleMetadata, Monetization},
        module_reference::ModuleReference,
        namespace::Namespace,
    };
    use super::{AccountBase, Config};
    pub const ADMIN: Admin = Admin::new(ADMIN_NAMESPACE);
    pub const FACTORY: Admin = Admin::new("fac");
    pub const CONFIG: Item<Config> = Item::new("cfg");
    pub const PENDING_MODULES: Map<&ModuleInfo, ModuleReference> = Map::new("pendm");
    pub const REGISTERED_MODULES: Map<&ModuleInfo, ModuleReference> = Map::new("lib");
    pub const YANKED_MODULES: Map<&ModuleInfo, ModuleReference> = Map::new("yknd");
    pub const MODULE_MONETIZATION: Map<(&Namespace, &str), Monetization> = Map::new("mod_m");
    pub const MODULE_METADATA: Map<&ModuleInfo, ModuleMetadata> = Map::new("mod_meta");
    pub const ACCOUNT_ADDRESSES: Map<AccountId, AccountBase> = Map::new("accs");
}
pub struct NamespaceIndexes<'a> {
    pub account_id: MultiIndex<'a, AccountId, AccountId, &'a Namespace>,
}
impl<'a> IndexList<AccountId> for NamespaceIndexes<'a> {
    fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<AccountId>> + '_> {
        let v: Vec<&dyn Index<AccountId>> = vec![&self.account_id];
        Box::new(v.into_iter())
    }
}
pub fn namespaces_info<'a>() -> IndexedMap<'a, &'a Namespace, AccountId, NamespaceIndexes<'a>> {
    let indexes = NamespaceIndexes {
        account_id: MultiIndex::new(|_pk, d| *d, "namespace", "namespace_account"),
    };
    IndexedMap::new("namespace", indexes)
}
use crate::objects::{
    account_id::AccountId,
    module::{Module, ModuleInfo, ModuleMetadata, ModuleStatus, ModuleVersion, Monetization},
    module_reference::ModuleReference,
    namespace::Namespace,
};
use cosmwasm_schema::QueryResponses;
use cosmwasm_std::{Addr, Coin, Order, Storage};
use state::MODULE_MONETIZATION;
use cw_storage_plus::{Index, IndexList, IndexedMap, MultiIndex};
use self::state::MODULE_METADATA;
#[cosmwasm_schema::cw_serde]
pub struct AccountBase {
    pub manager: Addr,
    pub proxy: Addr,
}
#[cosmwasm_schema::cw_serde]
pub struct InstantiateMsg {
    pub admin: String,
    pub allow_direct_module_registration_and_updates: Option<bool>,
    pub namespace_registration_fee: Option<Coin>,
}
#[cw_ownable::cw_ownable_execute]
#[cosmwasm_schema::cw_serde]
#[cfg_attr(feature = "interface", derive(cw_orch::ExecuteFns))]
pub enum ExecuteMsg {
    RemoveModule { module: ModuleInfo },
    YankModule { module: ModuleInfo },
    ProposeModules { modules: Vec<ModuleMapEntry> },
    SetModuleMonetization {
        module_name: String,
        namespace: Namespace,
        monetization: Monetization,
    },
    SetModuleMetadata {
        module: ModuleInfo,
        metadata: ModuleMetadata,
    },
    ApproveOrRejectModules {
        approves: Vec<ModuleInfo>,
        rejects: Vec<ModuleInfo>,
    },
    ClaimNamespace {
        account_id: AccountId,
        namespace: String,
    },
    RemoveNamespaces { namespaces: Vec<String> },
    AddAccount {
        account_id: AccountId,
        account_base: AccountBase,
    },
    UpdateConfig {
        allow_direct_module_registration_and_updates: Option<bool>,
        namespace_registration_fee: Option<Coin>,
    },
    SetFactory { new_factory: String },
}
#[derive(Default)]
#[cosmwasm_schema::cw_serde]
pub struct ModuleFilter {
    pub namespace: Option<String>,
    pub name: Option<String>,
    pub version: Option<String>,
    pub status: Option<ModuleStatus>,
}
#[cw_ownable::cw_ownable_query]
#[cosmwasm_schema::cw_serde]
#[derive(QueryResponses)]
#[cfg_attr(feature = "interface", derive(cw_orch::QueryFns))]
pub enum QueryMsg {
    #[returns(AccountBaseResponse)]
    AccountBase { account_id: AccountId },
    #[returns(ModulesResponse)]
    Modules { infos: Vec<ModuleInfo> },
    #[returns(NamespacesResponse)]
    Namespaces { accounts: Vec<AccountId> },
    #[returns(NamespaceResponse)]
    Namespace { namespace: Namespace },
    #[returns(ConfigResponse)]
    Config {},
    #[returns(ModulesListResponse)]
    ModuleList {
        filter: Option<ModuleFilter>,
        start_after: Option<ModuleInfo>,
        limit: Option<u8>,
    },
    #[returns(NamespaceListResponse)]
    NamespaceList {
        start_after: Option<String>,
        limit: Option<u8>,
    },
}
#[cosmwasm_schema::cw_serde]
pub struct AccountBaseResponse {
    pub account_base: AccountBase,
}
#[cosmwasm_schema::cw_serde]
pub struct ModulesResponse {
    pub modules: Vec<ModuleResponse>,
}
#[cosmwasm_schema::cw_serde]
pub struct ModuleResponse {
    pub module: Module,
    pub config: ModuleConfiguration,
}
#[non_exhaustive]
#[cosmwasm_schema::cw_serde]
pub struct ModuleConfiguration {
    pub monetization: Monetization,
    pub metadata: ModuleMetadata,
}
impl ModuleConfiguration {
    pub fn new(monetization: Monetization, metadata: ModuleMetadata) -> Self {
        Self {
            monetization,
            metadata,
        }
    }
    fn metadata_from_storage(storage: &dyn Storage, module: &ModuleInfo) -> ModuleMetadata {
        if let Ok(metadata) = MODULE_METADATA.load(storage, module) {
            return metadata;
        }
        if let Ok(metadata) = MODULE_METADATA.load(
            storage,
            &ModuleInfo {
                namespace: module.namespace.clone(),
                name: module.name.clone(),
                version: ModuleVersion::Latest,
            },
        ) {
            return metadata;
        }
        let potential_metadata = MODULE_METADATA
            .prefix((module.namespace.clone(), module.name.clone()))
            .range(storage, None, None, Order::Descending)
            .next();
        if let Some(Ok((_key, metadata))) = potential_metadata {
            return metadata;
        }
        "".to_string()
    }
    pub fn from_storage(storage: &dyn Storage, module: &ModuleInfo) -> Self {
        let monetization = MODULE_MONETIZATION
            .load(storage, (&module.namespace, &module.name))
            .unwrap_or(Monetization::None);
        let metadata = ModuleConfiguration::metadata_from_storage(storage, module);
        Self {
            monetization,
            metadata,
        }
    }
}
#[cosmwasm_schema::cw_serde]
pub struct ModulesListResponse {
    pub modules: Vec<ModuleResponse>,
}
#[cosmwasm_schema::cw_serde]
pub struct NamespaceResponse {
    pub account_id: AccountId,
    pub account_base: AccountBase,
}
#[cosmwasm_schema::cw_serde]
pub struct NamespacesResponse {
    pub namespaces: Vec<(Namespace, AccountId)>,
}
#[cosmwasm_schema::cw_serde]
pub struct NamespaceListResponse {
    pub namespaces: Vec<(Namespace, AccountId)>,
}
#[cosmwasm_schema::cw_serde]
pub struct ConfigResponse {
    pub factory: Addr,
}
#[cosmwasm_schema::cw_serde]
pub struct MigrateMsg {}