/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

//! Root-owned settings as an ordinary compiled capability, activated only by composition.
mod connections;
pub mod contract;
mod credential;
pub mod network;
pub mod preferences;
mod service;
mod setup;
pub mod usage;
use futures_util::future::BoxFuture;
use maka_agent_facts::language::LanguagePreference;
use maka_host_runtime::application::{NativeActivation, NativeOwner, NativeRegistry};
use schemars::JsonSchema;
use serde::Deserialize;
use std::sync::Arc;
#[derive(Default, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
struct Configuration {
    #[serde(default)]
    locale: String,
}

fn configuration_schema() -> serde_json::Value {
    serde_json::to_value(schemars::schema_for!(Configuration))
        .expect("settings configuration schema is serializable")
}

pub const IMPLEMENTATION: &str = "maka.settings";
pub const EXPORT: &str = "Settings";
pub fn provide(
    registry: &mut NativeRegistry,
    catalog: Arc<maka_providers::catalog::Catalog>,
) -> Result<(), String> {
    for (implementation, export, contract) in [
        (IMPLEMENTATION, EXPORT, contract::contract()),
        ("maka.settings.setup", "Setup", contract::setup_contract()),
        (
            "maka.settings.authentication",
            "Authentication",
            contract::authentication_contract(),
        ),
    ] {
        let catalog = catalog.clone();
        registry.insert(
            implementation.into(),
            Arc::new(move |context, input| {
                let contract = contract.clone();
                let catalog = catalog.clone();
                Box::pin(async move {
                    let opened = async {
                        let configuration: Configuration = serde_json::from_value(input)
                            .map_err(|_| "settings_configuration_invalid".to_owned())?;
                        let native_language = maka_config::language::native_language();
                        let persistence = context
                            .persistence()
                            .ok_or("settings_requires_persistence")?;
                        let root = persistence
                            .store()
                            .owned_root()
                            .map_err(|_| "settings_root_unavailable")?;
                        let store = maka_config::ConfigurationStore::for_root(root)
                            .await
                            .map_err(|_| "settings_store_unavailable")?;
                        Ok::<_, String>(Arc::new(service::Settings {
                            catalog,
                            configuration: Arc::new(store),
                            log: persistence.store().clone(),
                            configured_locale: LanguagePreference::from_locale(
                                &configuration.locale,
                            ),
                            native_language,
                        }))
                    }
                    .await;
                    match opened {
                        Ok(owner) => NativeActivation {
                            exports: Ok(std::collections::BTreeMap::from([(
                                export.into(),
                                maka_plugin_core::runtime::Published {
                                    contract,
                                    value: owner.clone()
                                        as Arc<dyn maka_host_runtime::application::Handler>,
                                },
                            )])),
                            owner,
                        },
                        Err(error) => NativeActivation {
                            exports: Err(error),
                            owner: Arc::new(Uninitialized),
                        },
                    }
                })
            }),
        )?;
    }
    Ok(())
}
struct Uninitialized;
impl NativeOwner for Uninitialized {
    fn prepare_retirement(
        &self,
    ) -> Option<Box<dyn maka_host_runtime::application::NativeRetirement>> {
        Some(Box::new(()))
    }
    fn close(&self) -> BoxFuture<'static, Result<(), String>> {
        Box::pin(async { Ok(()) })
    }
}

pub fn native() -> maka_plugin_core::package::NativeDefinition {
    maka_plugin_core::package::NativeDefinition::new(
        IMPLEMENTATION,
        configuration_schema(),
        [(EXPORT, contract::contract())],
    )
}

pub fn native_authentication() -> maka_plugin_core::package::NativeDefinition {
    maka_plugin_core::package::NativeDefinition::new(
        "maka.settings.authentication",
        configuration_schema(),
        [("Authentication", contract::authentication_contract())],
    )
}

pub fn native_setup() -> maka_plugin_core::package::NativeDefinition {
    maka_plugin_core::package::NativeDefinition::new(
        "maka.settings.setup",
        configuration_schema(),
        [("Setup", contract::setup_contract())],
    )
}
