from abc import ABC, abstractmethod
from typing import List, Optional, Any
from datetime import datetime

from analogai.foundation.modules.belief.belief import Belief
from analogai.foundation.modules.notion.notion import Notion
from analogai.foundation.core.value_objects.modifier import Modifier
from analogai.foundation.core.value_objects.relation import Relation


class BeliefRepository(ABC):

    @abstractmethod
    def save(self, belief: Belief) -> Belief:
        pass

    @abstractmethod
    def find(self, subject_notion: Notion, complement_notion: Notion,
             relation: Relation,
             modifier: Optional[Modifier] = None,
             quantity: Optional[float] = None) -> Optional[Belief]:
        pass

    @abstractmethod
    def delete(self, belief: Belief) -> None:
        pass

    @abstractmethod
    def search_by_notions(self, subject_notion: Notion, complement_notion: Notion,
                          modifier: Optional[Modifier] = None) -> List[Belief]:
        pass

    @abstractmethod
    def search_by_subject_notion(self, subject_notion: Notion,
                                modifier: Optional[Modifier] = None) -> List[Belief]:
        pass

    @abstractmethod
    def search_by_complement_notion(self, complement_notion: Notion,
                                modifier: Optional[Modifier] = None) -> List[Belief]:
        pass

    @abstractmethod
    def find_by_agent_id(self, agent_id: str) -> List[Belief]:
        pass

    @abstractmethod
    def get_recently_updated(self, agent_id: str, since: datetime) -> List[Belief]:
        pass

    @abstractmethod
    def clear_cache(self, belief_id: Optional[str] = None) -> None:
        pass

    @abstractmethod
    def search_by_modifier(self, modifier: Modifier) -> List[Belief]:
        pass

    @abstractmethod
    def find_belief_by_statement_id(self, statement_id: str) -> Optional[Belief]:
        pass

    def set_belief_service(self, belief_service: Any) -> None:
        pass

    def set_time_service(self, time_service: Any) -> None:
        pass