import unittest
import sys
for path in ['../', './']:
    sys.path.insert(1, path)

# python -m unittest discover
from processing.clustering import ClusterResultConverter, ClusterResult
from typing import List, Dict, Any

class TestClusterResult(unittest.TestCase):
    converter:ClusterResultConverter = None

    def setUp(self):
    
        self.converter = ClusterResultConverter()
    

    def test_result_undefined_feature(self):
        cluster_groups = self._get_some_cluster_groups_1d()
        cluster_res = self.converter.convert_to_cluster_results(
            cluster_groups=cluster_groups,
            features=[]
        )

        self.assert_correct_cluster_result_len(cluster_groups, cluster_res)
        self.assert_correct_cluster_result_labels(['n.a.','n.a.','n.a.'], cluster_res)

    def test_result_1d_feature(self):
        cluster_groups = self._get_some_cluster_groups_1d()
        cluster_res = self.converter.convert_to_cluster_results(
            cluster_groups=cluster_groups,
            features=['v']
        )
        

        self.assert_correct_cluster_result_len(cluster_groups, cluster_res)
        self.assert_correct_cluster_result_labels(['-1.0 -- 1.0','10.0 -- 11.0','2.0 -- 2.0'], cluster_res)

    def test_result_2d_features(self):

        cluster_groups = self._get_some_cluster_groups_2d()
        cluster_res = self.converter.convert_to_cluster_results(
            cluster_groups=cluster_groups,
            features=['v', 'u']
        )

        self.assert_correct_cluster_result_len(cluster_groups, cluster_res)
        self.assert_correct_cluster_result_labels([str((0.0,0.0)), str((10.5,10.5)), str((2.0,2.0)), str((3.0,6.0))], cluster_res)

    

    #region Custom Assertions

    def assert_correct_cluster_result_len(self, expected: 'original dict of lists', actual: Dict[Any, ClusterResult]):
        self.assertEqual(len(expected), len(actual))
        for i in range(len(expected)):
            self.assertEqual(len(expected[i]), len(actual[i].nodes))
            self.assertEqual(expected[i], actual[i].nodes)


    def assert_correct_cluster_result_labels(self, expected: List[str], actual: Dict[Any, ClusterResult]):
        self.assertEqual(len(expected), len(actual))
        for i in range(len(expected)):
            self.assertEqual(expected[i], actual[i].label)

    #endregion Custom Assertions

    #region helper methods
    def _get_some_cluster_groups_1d(self):
        return {
            0: [{'v':'0'}, {'v':'1'}, {'v':'-1'}],
            1: [{'v':'10'}, {'v':'11'}],
            2: [{'v':'2'}],
        }

    def _get_some_cluster_groups_2d(self):
        return {
            0: [{'v':'0', 'u':'0'}, {'v':'1', 'u':'1'}, {'v':'-1', 'u':'-1'}],
            1: [{'v':'10', 'u':'10'}, {'v':'11', 'u':'11'}],
            2: [{'v':'2', 'u':'2'}],
            3: [{'v':'7', 'u':'7'}, {'v':'5', 'u':'3'}, {'v':'-3', 'u':'8'}],
        }
    #endregion helper methods

if __name__ == '__main__':
    unittest.main()