import unittest
import sys
sys.path.insert(1, '../')

# python -m unittest discover
from db.entities.cluster import Cluster
from db.entities import TimeCluster, LocationCluster

from datetime import date, datetime
import json


class TestCluster(unittest.TestCase):
    def test_init_Cluster(self):
        c = Cluster(1, [1, 2, 3])

        self.assertEqual(1, c.cluster_label)
        self.assertEqual([1, 2, 3], c.nodes)


class TestLocationCluster(unittest.TestCase):
    def setUp(self):
        self.c = LocationCluster(1, [1, 2, 3])

    def test_init_individualArguments(self):
        c = LocationCluster(1, [1, 2, 3])

        self.assertEqual('1', c.id)
        self.assertEqual(1, c.cluster_label)
        self.assertEqual([1, 2, 3], c.nodes)

    def test_init_dictArgument(self):
        dict_ = {'id': '123', 'cluster_label': 1, 'nodes': [1, 2, 3]}
        c = LocationCluster(location_dict=dict_)

        self.assertEqual('123', c.id)
        self.assertEqual(1, c.cluster_label)
        self.assertEqual([1, 2, 3], c.nodes)

    def test_init_dictArgument_fromDb(self):
        dict_ = {'id': '123', 'cluster_label': 1, 'nodes': '[1, 2, 3]'}
        c = LocationCluster(location_dict=dict_, from_db=True)

        self.assertEqual('123', c.id)
        self.assertEqual(1, c.cluster_label)
        self.assertEqual([1, 2, 3], c.nodes)

    def test_to_serializable_dict_noDb(self):
        c_dict = self.c.to_serializable_dict()

        self.assertEqual(self.c.id, c_dict['id'])
        self.assertEqual(self.c.cluster_label, c_dict['cluster_label'])
        self.assertEqual(self.c.nodes, c_dict['nodes'])

    def test_from_serializable_dict_noDb(self):
        new_c = LocationCluster()
        new_c.from_serializable_dict(self.c.to_serializable_dict())

        self.assertEqual(self.c.id, new_c.id)
        self.assertEqual(str(self.c), str(new_c))

    def test_to_serializable_dict_db_jsonNodes(self):
        c_dict = self.c.to_serializable_dict(for_db=True)

        self.assertEqual(self.c.id, c_dict['id'])
        self.assertEqual(self.c.cluster_label, c_dict['cluster_label'])
        self.assertEqual(self.c.nodes, json.loads(c_dict['nodes']))

    def test_from_serializable_dict_fromDb(self):
        new_c = LocationCluster()
        new_c.from_serializable_dict(
            self.c.to_serializable_dict(for_db=True), from_db=True)

        self.assertEqual(self.c.id, new_c.id)
        self.assertEqual(str(self.c), str(new_c))


class TestTimeCluster(unittest.TestCase):

    def setUp(self):
        self.date_ = date(2020, 1, 1)
        self.c = TimeCluster(self.date_, 14, 1, [1, 2, 3])

    def test_init_individualArguments(self):
        c = TimeCluster(self.date_, 14, 1, [1, 2, 3])

        self.assertEqual(f'{self.date_}-14-1', c.id)
        self.assertEqual(self.date_, c.date)
        self.assertEqual(14, c.hour)
        self.assertEqual(1, c.cluster_label)
        self.assertEqual([1, 2, 3], c.nodes)

    def test_init_dictArgument(self):
        dict_ = {'id': '123', 'cluster_label': 1, 'nodes': [1, 2, 3],
                 'date': str(self.date_), 'hour': 14}
        c = TimeCluster(time_dict=dict_)

        self.assertEqual('123', c.id)
        self.assertEqual(self.date_, c.date)
        self.assertEqual(14, c.hour)
        self.assertEqual(1, c.cluster_label)
        self.assertEqual([1, 2, 3], c.nodes)

    def test_init_dictArgument_fromDb(self):
        dict_ = {'id': '123', 'cluster_label': 1, 'nodes': '[1, 2, 3]',
                 'date': str(self.date_), 'hour': 14}
        c = TimeCluster(time_dict=dict_, from_db=True)

        self.assertEqual('123', c.id)
        self.assertEqual(self.date_, c.date)
        self.assertEqual(14, c.hour)
        self.assertEqual(1, c.cluster_label)
        self.assertEqual([1, 2, 3], c.nodes)

    def test_to_serializable_dict_noDb(self):
        c_dict = self.c.to_serializable_dict()

        self.assertEqual(self.c.id, c_dict['id'])
        self.assertEqual(self.c.cluster_label, c_dict['cluster_label'])
        self.assertEqual(self.c.nodes, c_dict['nodes'])
        self.assertEqual(self.c.date, datetime.strptime(
            c_dict['date'], '%Y-%m-%d').date())
        self.assertEqual(self.c.hour, c_dict['hour'])

    def test_from_serializable_dict_noDb(self):
        new_c = TimeCluster()
        new_c.from_serializable_dict(self.c.to_serializable_dict())

        self.assertEqual(self.c.id, new_c.id)
        self.assertEqual(str(self.c), str(new_c))

    def test_to_serializable_dict_fromDb_jsonNodes(self):
        c_dict = self.c.to_serializable_dict(for_db=True)

        self.assertEqual(self.c.id, c_dict['id'])
        self.assertEqual(self.c.cluster_label, c_dict['cluster_label'])
        self.assertEqual(self.c.nodes, json.loads(c_dict['nodes']))
        self.assertEqual(self.c.date, datetime.strptime(
            c_dict['date'], '%Y-%m-%d').date())
        self.assertEqual(self.c.hour, c_dict['hour'])

    def test_from_serializable_dict_fromDb(self):
        new_c = TimeCluster()
        new_c.from_serializable_dict(
            self.c.to_serializable_dict(for_db=True), from_db=True)

        self.assertEqual(self.c.id, new_c.id)
        self.assertEqual(str(self.c), str(new_c))


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