use std::collections::HashMap;

use futures::StreamExt;
use taganak_orm::GraphORM;

use crate::{graphs, prelude::*};

pub mod memory;

pub trait DatasetConfig: Clone {
    type Dataset: ConfigurableDataset<Config = Self>;

    fn into_dataset(self) -> Result<Self::Dataset, DatasetError>
    where
        Self: Sized,
    {
        Self::Dataset::from_config(self)
    }
}

pub trait ConfigurableDataset: Dataset {
    type Config: DatasetConfig<Dataset = Self>;

    fn from_config(config: Self::Config) -> Result<Self, DatasetError>
    where
        Self: Sized;
}

#[derive(Debug, Clone, PartialEq, GraphORM)]
#[rdf(
    prefix(ns="sdk", iri="http://sdk.taganak.net/vocab/taganak#"),
    rdf_type = "sdk:GraphDatasetConfig"
)]
pub struct GraphDatasetConfig {
    #[rdf(predicate="sdk:defaultGraph")]
    default_graph: GraphConfigs,
    #[rdf(predicate="sdk:graph")]
    graphs: HashMap<Arc<Term>, GraphConfigs>,
}

#[derive(thiserror::Error, Debug)]
pub enum FromGraphError {
    #[error("provided subject is not a dataset")]
    NotDataset,
    #[error(
        "provided dataset does not carry <http://sdk.taganak.net/vocab/taganak#datasetConfig>"
    )]
    NoDatasetConfig,
    #[error("provided datasetConfig is not of rdf_type <http://sdk.taganak.net/vocab/taganak#datasetConfig>")]
    NotDatasetConfig,
    #[error("Default graph is missing from subject")]
    NoDefaultGraph,
    #[error(transparent)]
    GraphConfigsError(#[from] graphs::FromGraphError),
    #[error(transparent)]
    GraphError(#[from] GraphError),
}
