import pymongo
import network_constants as netconst
from database.MongoRepositoryBase import MongoRepositoryBase
import json

from db.agi.agi_repository import AgiRepository

from db.entities import *
from typing import List


class Repository(MongoRepositoryBase):
    '''This is a repository for MongoDb.'''

    def __init__(self):
        super().__init__(netconst.COMMUNITY_DETECTION_DB_HOSTNAME,
                         netconst.COMMUNITY_DETECTION_DB_PORT,
                         'communityDetectionDb')

        self._location_collection = 'location'
        self._location_cluster_collection = 'location_cluster'
        self._time_cluster_collection = 'time_cluster'
        self._user_cluster_graph_collection = 'user_cluster_graph'
        self._layer_collection = 'layer'
        self._clusterset_collection = 'cluster_set'

        self.agi_repo = AgiRepository()

    def add_location(self, location: Location):
        super().insert_entry(self._location_collection, location.to_serializable_dict())

    def get_locations(self) -> List[Location]:
        locations = super().get_entries(self._location_collection)
        return [Location(l) for l in locations]

    def get_agi_locations(self) -> List[Location]:
        agi_locations = self.agi_repo.getLocations()
        return [Location(agi_loc) for agi_loc in agi_locations]

    def add_location_cluster(self, cluster: LocationCluster):
        super().insert_entry(self._location_cluster_collection,
                             cluster.to_serializable_dict(for_db=True))

    def get_location_clusters(self) -> List[LocationCluster]:
        clusters = super().get_entries(self._location_cluster_collection)
        return [LocationCluster(location_dict=c, from_db=True) for c in clusters]

    def add_time_cluster(self, cluster: TimeCluster):
        super().insert_entry(self._time_cluster_collection,
                             cluster.to_serializable_dict(for_db=True))

    def get_time_clusters(self) -> List[TimeCluster]:
        clusters = super().get_entries(self._time_cluster_collection)
        return [TimeCluster(time_dict=c, from_db=True) for c in clusters]

    def add_user_cluster_graph(self, user_graph: UserClusterGraph):
        super().insert_entry(self._user_cluster_graph_collection,
                             user_graph.to_serializable_dict(for_db=True))

    def get_user_cluster_graphs(self) -> List[UserClusterGraph]:
        user_graphs = super().get_entries(self._user_cluster_graph_collection)
        return [UserClusterGraph(dict_=u, from_db=True) for u in user_graphs]

    def add_layer(self, layer: Layer):
        super().insert_entry(self._layer_collection, layer.to_serializable_dict())

    def get_layers(self) -> List[Layer]:
        entries = super().get_entries(self._layer_collection)
        return [Layer(e) for e in entries]

    def add_clusterset(self, cluster_set: ClusterSet):
        super().insert_entry(self._clusterset_collection, cluster_set.to_serializable_dict())

    def get_clustersets(self) -> List[ClusterSet]:
        entries = super().get_entries(self._clusterset_collection)
        return [ClusterSet(cluster_set_dict=e) for e in entries]