use serde_json::{Value, json};

use crate::client::Client;
use crate::error::Error;
use crate::params::{
    BlobsParams, DecimalFractionsParams, GaussiansParams, IntegerSequencesMultiformParams,
    IntegerSequencesUniformParams, IntegersParams, StringsParams, UuidsParams,
};
use crate::types::{BasicResult, UsageResult};

impl Client {
    pub async fn generate_integers(
        &self,
        p: IntegersParams,
    ) -> Result<BasicResult<Vec<Value>>, Error> {
        let params = json!({
            "n": p.n,
            "min": p.min,
            "max": p.max,
            "replacement": p.replacement,
            "base": p.base,
            "pregeneratedRandomization": p.pregenerated,
        });
        self.call_keyed("generateIntegers", params).await
    }

    pub async fn generate_integer_sequences_uniform(
        &self,
        p: IntegerSequencesUniformParams,
    ) -> Result<BasicResult<Vec<Vec<Value>>>, Error> {
        let params = json!({
            "n": p.n,
            "length": p.length,
            "min": p.min,
            "max": p.max,
            "replacement": p.replacement,
            "base": p.base,
            "pregeneratedRandomization": p.pregenerated,
        });
        self.call_keyed("generateIntegerSequences", params).await
    }

    pub async fn generate_integer_sequences_multiform(
        &self,
        p: IntegerSequencesMultiformParams,
    ) -> Result<BasicResult<Vec<Vec<Value>>>, Error> {
        let params = json!({
            "n": p.n,
            "length": p.length,
            "min": p.min,
            "max": p.max,
            "replacement": p.replacement,
            "base": p.base,
            "pregeneratedRandomization": p.pregenerated,
        });
        self.call_keyed("generateIntegerSequences", params).await
    }

    pub async fn generate_decimal_fractions(
        &self,
        p: DecimalFractionsParams,
    ) -> Result<BasicResult<Vec<f64>>, Error> {
        let params = json!({
            "n": p.n,
            "decimalPlaces": p.decimal_places,
            "replacement": p.replacement,
            "pregeneratedRandomization": p.pregenerated,
        });
        self.call_keyed("generateDecimalFractions", params).await
    }

    pub async fn generate_gaussians(
        &self,
        p: GaussiansParams,
    ) -> Result<BasicResult<Vec<f64>>, Error> {
        let params = json!({
            "n": p.n,
            "mean": p.mean,
            "standardDeviation": p.std_dev,
            "significantDigits": p.significant_digits,
            "pregeneratedRandomization": p.pregenerated,
        });
        self.call_keyed("generateGaussians", params).await
    }

    pub async fn generate_strings(
        &self,
        p: StringsParams,
    ) -> Result<BasicResult<Vec<String>>, Error> {
        let params = json!({
            "n": p.n,
            "length": p.length,
            "characters": p.characters,
            "replacement": p.replacement,
            "pregeneratedRandomization": p.pregenerated,
        });
        self.call_keyed("generateStrings", params).await
    }

    pub async fn generate_uuids(&self, p: UuidsParams) -> Result<BasicResult<Vec<String>>, Error> {
        let params = json!({
            "n": p.n,
            "pregeneratedRandomization": p.pregenerated,
        });
        self.call_keyed("generateUUIDs", params).await
    }

    pub async fn generate_blobs(&self, p: BlobsParams) -> Result<BasicResult<Vec<String>>, Error> {
        let params = json!({
            "n": p.n,
            "size": p.size,
            "format": p.format,
            "pregeneratedRandomization": p.pregenerated,
        });
        self.call_keyed("generateBlobs", params).await
    }

    pub async fn get_usage(&self) -> Result<UsageResult, Error> {
        self.call_keyed("getUsage", json!({})).await
    }
}
