"""
    @release_date  : $release_date
    @version       : $release_version
    @author        : Christos Matsingos, Ka Fu Man

    This file is part of the TrIPP software
    (https://github.com/fornililab/TrIPP).
    Copyright (c) 2024 Christos Matsingos, Ka Fu Man and Arianna Fornili.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, version 3.

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

from sklearn.cluster import DBSCAN
from tripp._density_clustering_utilities_ import find_density_clustering_centroids

def dbscan_clustering(
    eps,
    min_samples,
    metric,
    metric_params,
    algorithm,
    leaf_size,
    p,
    n_jobs,
    clustering_matrix,
    frames,
    find_centroid,
    trajectory_names,
):
    """
    Function to run DBSCAN clustering from scikit-learn.
    Standard DBSCAN parameters can be found in the scikit-learn documentation:
    https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html
    
    Parameters
    ----------
    clustering_matrix : np.ndarray
       The clustering matrix (feature matrix) created by the create_clustering_matrix function.
    frames : list
        A list of frames corresponding to the points to be clustered.
        Generated by the create_clustering_matrix function.
    find_centroid : bool
        If True, the function will return the cluster centroids.
        If False, it will only return the labels.
    trajectory_names : np.ndarray
        An array of names of the trajectories to be clustered.
        Generated by the create_clustering_matrix function.
    Returns
    -------
    labels: np.ndarray
        An array of cluster labels for each point in the feature matrix.
    
    If `find_centroid=True`:
    
    cluster_centers: list
        Indices of the cluster centers within their individual trajectories (local indices). 
        Indices start from 0 for each trajectory.
    cluster_center_indices: list
        Indices of the cluster centers within the full feature matrix (global indices).
    cluster_centers_trajectories: list
        Trajectory names of the cluster centers.
    """

    dbscan_clustering = DBSCAN(
        eps=eps,
        min_samples=min_samples,
        metric=metric,
        metric_params=metric_params,
        algorithm=algorithm,
        leaf_size=leaf_size,
        p=p,
        n_jobs=n_jobs,
    )
    dbscan_clustering.fit(clustering_matrix)
    labels = dbscan_clustering.labels_

    if find_centroid is True:
        (cluster_centers, cluster_center_indices, cluster_centers_trajectories
        ) = find_density_clustering_centroids(labels, frames, trajectory_names, clustering_matrix)
        return (
            labels,
            cluster_centers,
            cluster_center_indices,
            cluster_centers_trajectories,
        )

    elif find_centroid is False:
        return labels
