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

from db.entities import *
from typing import List


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

    def __init__(self):
        super().__init__(netconst.ROLESTAGE_DISCOVERY_DB_HOSTNAME,
                         netconst.ROLESTAGE_DISCOVERY_DB_PORT,
                         'roleStageDb')

        self._layer_collection = 'layers'
        self._layer_nodes_collection = 'layer_nodes'
        self._clusters_collection = 'clusters'
        self._time_slice_collection = 'time_slices'

#region Layers
    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 get_layer(self, layer_name) -> Layer:
        entries = super().get_entries(self._layer_collection, selection={'layer_name': layer_name})
        entries = [Layer(e) for e in entries]

        if entries is not None and len(entries) > 0:
            return entries[0]
        else:
            return None

    def add_layer_node(self, node: dict):
        super().insert_entry(self._layer_nodes_collection, node)

    def add_layer_nodes(self, nodes:List[dict]):
        super().insert_many(self._layer_nodes_collection, nodes)

    def get_layer_nodes(self, layer_name: str) -> dict:
        '''Returns all nodes for the layer.'''
        entries = super().get_entries(self._layer_nodes_collection, selection={'layer_name': layer_name}, projection={'_id': 0})
        return [e for e in entries]

#endregion

#region Clusters
    def add_clusters(self, clusters: List[Cluster]):
        cluster_dicts = [c.to_serializable_dict(for_db=True) for c in clusters]
        super().insert_many(self._clusters_collection, cluster_dicts)
        
    def get_clusters_for_layer(self, layer_name: str) -> List[Cluster]:
        entries = super().get_entries(self._clusters_collection, selection={'layer_name': layer_name}, projection={'_id': 0})
        return [Cluster(cluster_dict=e, from_db=True) for e in entries]
    
#endregion

#region TimeSlice
    def add_time_slice(self, timeslice: TimeSlice):
        super().insert_entry(self._time_slice_collection, timeslice.to_serializable_dict(for_db=True))

    def get_time_slices(self) -> List[TimeSlice]:
        '''Returns all time slices.'''
        entries = super().get_entries(self._time_slice_collection)
        return [TimeSlice(None, None, time_slice_dict=e, from_db=True) for e in entries]

    def get_time_slices_by_name(self, layer_name) -> List[TimeSlice]:
        '''Returns all time slices with the given layer_name.'''
        entries = super().get_entries(self._time_slice_collection, selection={'layer_name': layer_name})
        return [TimeSlice(None, None, time_slice_dict=e, from_db=True) for e in entries]

    def remove_all_time_slices(self):
        super().drop_collection(self._time_slice_collection)

#endregion