import logging
from typing import Optional, List, Dict, Type

from dataclasses import dataclass

from evidently.analyzers.data_drift_analyzer import DataDriftOptions
from evidently.pipeline.column_mapping import ColumnMapping
from evidently.runner.loader import DataLoader, SamplingOptions, DataOptions


@dataclass
class RunnerOptions:
    reference_data_path: str
    reference_data_options: DataOptions
    reference_data_sampling: Optional[SamplingOptions]
    current_data_path: Optional[str]
    current_data_options: Optional[DataOptions]
    current_data_sampling: Optional[SamplingOptions]
    column_mapping: ColumnMapping
    options: List[object]
    output_path: str


options_mapping: Dict[str, Type] = {
    'data_drift': DataDriftOptions
}


def parse_options(raw_dict: Optional[Dict[str, Dict[str, object]]]) -> List[object]:
    if raw_dict is None:
        return []
    result = []
    for key, params in raw_dict.items():
        opt_class = options_mapping.get(key, None)
        if opt_class is None:
            raise ValueError(f"No options with id {key} exists")
        result.append(opt_class(**params))
    return result


class Runner:
    def __init__(self, options: RunnerOptions):
        self.options = options

    def _parse_data(self):
        loader = DataLoader()

        reference_data = loader.load(self.options.reference_data_path,
                                     self.options.reference_data_options,
                                     self.options.reference_data_sampling)
        logging.info(f"reference dataset loaded: {len(reference_data)} rows")
        if self.options.current_data_path:
            current_data = loader.load(self.options.current_data_path,
                                       self.options.current_data_options,
                                       self.options.current_data_sampling)
            logging.info(f"current dataset loaded: {len(current_data)} rows")
        else:
            current_data = None

        return reference_data, current_data
