from core.explanations.validators.ClusterExplanationValidator import ClusterExplanationValidator
from core.explanations.factories.BaseExplanationFactory import BaseExplanationFactory
from core.explanations.generator.ExplanationGenerator import ExplanationGenerator
from core.explanations.utils import calc_samples_prototype

import numpy as np


class ClusterExplanationFactory(BaseExplanationFactory):

    def __init__(self, model, label, prototype):
        super().__init__(model, label)
        self.prototype = prototype

    def get_explanations(self, samples, epsilon, delta, ordering, num_explanations, num_consumers, use_progress_bar):
        # Filter the samples whose classification does not match the label.
        samples = self.model.filter(samples, self.label)

        if len(samples) == 0:
            raise ValueError(f"No samples found with label {self.label}.")

        samples_prot = calc_samples_prototype(samples, self.prototype, flatten=False)
        samples_size = np.prod(samples[0].shape)

        validator = ClusterExplanationValidator(
             model=self.model,
             label=self.label,
             samples=samples,
             epsilon=epsilon,
             delta=delta
        )

        generator = ExplanationGenerator(
            validator=validator,
            ordering=ordering,
            num_consumers=num_consumers,
            sample_size=samples_size
        )

        return generator.get_explanations(
            sample=samples_prot,
            num_explanations=num_explanations,
            use_progress_bar=use_progress_bar
        )
