import hdbscan
import numpy as np
import pandas as pd

from oolearning.enums.Metric import Metric
from oolearning.evaluators.ScoreClusteringBase import ScoreClusteringBase
from oolearning.evaluators.UtilityFunctionMixin import UtilityFunctionMixin


class DensityBasedClusteringValidationScore(UtilityFunctionMixin, ScoreClusteringBase):
    """
    A score/index for density-based clustering techniques
    implemented via `hdbscan.validity.validity_index()`: http://hdbscan.readthedocs.io/en/latest/api.html
    based on: https://epubs.siam.org/doi/pdf/10.1137/1.9781611973440.96
    """
    def __init__(self):
        super().__init__()

    @property
    def name(self) -> str:
        return Metric.DENSITY_BASED_CLUSTERING_VALIDATION.value

    def _calculate(self, clustered_data: pd.DataFrame, clusters: np.ndarray) -> float:
        """
        :param clustered_data: the dataset passed into the clustering algorithm (i.e. after transformations)
        :param clusters: clusters generated by clustering algorithm
        :return:
        """
        return hdbscan.validity.validity_index(X=clustered_data.values.astype(np.float64), labels=clusters)
