// Copyright 2023 Salesforce, Inc. All rights reserved.
use pdk_core::classy::client::Service;
use pdk_core::client::service_name;

use crate::api::metadata::PolicyMetadata;
use crate::api::status::Status;
use crate::api::types::Bytes;
use crate::hostcalls;
use crate::hostcalls::{log, FlexLogLevel};

pub mod metadata;
pub mod status;
pub mod types;

pub trait FlexAbi {
    fn get_policy_metadata(&self) -> &PolicyMetadata;
    fn get_configuration(&self) -> &Bytes;
    fn log_trace(&self, msg: &str);
    fn log_debug(&self, msg: &str);
    fn log_info(&self, msg: &str);
    fn log_warn(&self, msg: &str);
    fn log_error(&self, msg: &str);
    fn service_create(&self, service: Service) -> Result<(), Status>;
}

pub(crate) struct FlexAbiImpl {
    pub(crate) metadata: PolicyMetadata,
    pub(crate) config: Bytes,
}

impl FlexAbi for FlexAbiImpl {
    fn get_policy_metadata(&self) -> &PolicyMetadata {
        &self.metadata
    }

    fn get_configuration(&self) -> &Bytes {
        &self.config
    }

    fn log_trace(&self, msg: &str) {
        log(FlexLogLevel::Trace, msg);
    }

    fn log_debug(&self, msg: &str) {
        log(FlexLogLevel::Debug, msg);
    }

    fn log_info(&self, msg: &str) {
        log(FlexLogLevel::Info, msg);
    }

    fn log_warn(&self, msg: &str) {
        log(FlexLogLevel::Warn, msg);
    }

    fn log_error(&self, msg: &str) {
        log(FlexLogLevel::Error, msg);
    }

    /// Registering services ABI functions
    fn service_create(&self, service: Service) -> Result<(), Status> {
        let service_name_optional_service = service_name(
            self.get_policy_metadata().policy_name(),
            service.uri().authority(),
        );

        hostcalls::service_create(
            service_name_optional_service.as_str(),
            self.get_policy_metadata().policy_namespace(),
            service.uri().to_string().as_str(),
        )?;

        Ok(())
    }
}
