import requests
from enum import Enum
from logging import Logger
from typing import AnyStr, Optional, Iterable, Generator, List, Dict

from .enums import RequestStatus, Protocol, Location, RuleSourceSystem
from .port_range import PortRange
from .rule import Rule
from .rule_request import RuleRequest

class PuncherApi(object):
    LOGGER: Logger

    class Endpoints(Enum):
        production: AnyStr
        testing: AnyStr
        development: AnyStr

    def __init__(self, endpoint: Endpoints = Endpoints.production, oauth_token: Optional[AnyStr] = None):
        self.BASE_URL: AnyStr = ...
        self._session: requests.Session = ...
        ...

    @staticmethod
    def _raise_error(response: requests.Response) -> Dict:
        ...

    def _request_get(self, url: AnyStr, **params) -> Dict:
        ...

    def _make_modifying_request(self, action: AnyStr, url: AnyStr, **params) -> Dict:
        ...

    def get_requests(
        self,
        status: Optional[RequestStatus, Iterable[RequestStatus]] = None,
        source: Optional[AnyStr] = None,
        responsible: Optional[AnyStr] = None,
        author: Optional[AnyStr] = None
    ) -> Generator[RuleRequest]:
        ...

    def create_request(self, rule_request: RuleRequest) -> RuleRequest:  # TODO: Specify exception
        ...

    def update_request(self, rule_request: RuleRequest) -> RuleRequest:
        ...

    def reject_request(self, rule_request_id: AnyStr) -> RuleRequest:
        ...

    def approve_request(self, rule_request_id: AnyStr) -> RuleRequest:
        ...

    def get_rules(self, source: Optional[AnyStr]=None, destination: Optional[AnyStr]=None, protocol: Optional[Protocol]=None, locations: Optional[Iterable[Location]] = None,
                  ports: Optional[Iterable[PortRange]]=None, systems: Optional[Iterable[RuleSourceSystem]] = RuleSourceSystem.all, ) -> Generator[Rule]:
        ...

    def delete_rule(self, rule_id: AnyStr, comment: AnyStr) -> RuleRequest:
        ...

    def suggest_sources(self, s: AnyStr) -> List[Dict[AnyStr, AnyStr]]:
        ...

    def suggest_destinations(self, s: AnyStr) -> List[Dict[AnyStr, AnyStr]]:
        ...
