from core.explanations.validators.BaseExplanationValidator import BaseExplanationValidator
from core.explanations.utils import calc_samples_std


class ClusterExplanationValidator(BaseExplanationValidator):
    samples_std = None

    def __init__(self, model, label, samples, epsilon, delta):
        # All the samples should have the same shape.
        super().__init__(model, label, samples[0].shape)

        # Filter the samples whose classification does not match the label.
        samples = model.filter(samples, label)

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

        self.samples_std = calc_samples_std(samples)
        self.use_samples_std = len(samples) > 1

        self.epsilon = epsilon
        self.delta = delta

    def _get_bounds(self, sample, explanation, feature):
        if feature in explanation:
            gamma = self.delta * self.epsilon

            if self.use_samples_std:
                gamma *= self.samples_std[feature]

            return (sample[feature] - gamma, sample[feature] + gamma)
        else:
            return (sample[feature] - self.epsilon, sample[feature] + self.epsilon)
