#global imports
from db.repository import Repository
from db.entities.layer_adapter import LayerAdapter

from typing import List


class LayerAdapterService:

    _repository = Repository()

    @staticmethod
    def all_use_cases() -> List[str]:
        return LayerAdapterService._repository.all_use_cases()
    
    @staticmethod
    def delete_all_use_cases():
        LayerAdapterService._repository.delete_all_use_cases()
        LayerAdapterService._repository.delete_all_layers()
    
    @staticmethod
    def delete_use_case(name:str):
        LayerAdapterService._repository.delete_all_use_cases_with_name(name)

    @staticmethod
    def all() -> List[LayerAdapter]:
        '''
        Return all currently defined layers
        '''
        return LayerAdapterService._repository.all()
    
    @staticmethod
    def all_for_use_case(use_case: str) -> List[LayerAdapter]:
        '''
        Return all currently defined layers that belong to the
        given use-case
        '''
        return LayerAdapterService._repository.all_for_use_case(use_case)

    @staticmethod
    def update(layer: LayerAdapter):
        '''
        Overwrite the stored instance with the given one which is 
        identified by the layer name

        @params:
            layer - Required : layer object holding the current data
        '''
        LayerAdapterService._repository.update(layer)

    @staticmethod
    def update_use_case(layer: LayerAdapter, use_case:str):
        '''
        Overwrite the stored instance with the given one which is 
        identified by the layer name

        @params:
            layer - Required : layer object holding the current data
        '''
        LayerAdapterService._repository.update_use_case(layer, use_case)

    @staticmethod
    def add(name: str, use_case: str):
        '''
        Add a new layer to the DB. Attribute mapping and cluster
        attributes will be empty per default

        @params:
            name        - Required : Unique name for a layer.
            use_case    - Required : String-identifier for the use-case
        '''
        adapter_new = LayerAdapter(name, use_case, {}, [])

        LayerAdapterService._repository.add(adapter_new)

    @staticmethod
    def add_complete(layer: LayerAdapter):
        '''
        Add a new layer to the DB. Attribute mappings and cluster
        attributes of the given layer are used

        @params:
            layer - Required : layer object holding correct data
        '''
        LayerAdapterService._repository.add(layer)

    @staticmethod
    def delete(layer: LayerAdapter):
        '''
        delete all layers with the given name.

        @params:
            layer - Required : layer object to remove from the DB
        '''
        use_case = layer.use_case
        LayerAdapterService._repository.delete_all_with_name_and_use_case(layer.name, use_case)

        # remove use-case if it is not needed
        layers_in_use_case = LayerAdapterService.all_for_use_case(use_case)
        if len(layers_in_use_case) == 0:
            LayerAdapterService.delete_use_case(use_case)

    @staticmethod
    def one(name: str, use_case: str) -> LayerAdapter:
        '''
        Retrieve a single layer from the DB. Returns None if no layer
        was found under this name.

         @params:
            name        - Required : Unique name for a layer
            use_case    - Required : String-identifier for the use-case
        '''
        result = LayerAdapterService._repository.one_by_name_and_usecase(name, use_case)

        if len(result) == 1:
            return LayerAdapter.from_serializable_dict(result[0])
        else:
            return None
