import inspect
from abc import ABC, abstractmethod
from typing import Type, Union, Optional

from messageprocessor import MessageProcessor
from simplehttprouter import Route

from .dto import RouteBuildParams
from ..model import OpenapiModel, PathModel, SchemaModel, ComponentsModel


class OpenApiModelBuilder(ABC):

    @abstractmethod
    def add_processor_path(
        self,
        route: Route,
        processor: Union[MessageProcessor, Type[MessageProcessor]],
    ) -> PathModel:
        raise NotImplementedError()

    @abstractmethod
    def add_interactor_path(self, route_params: RouteBuildParams) -> PathModel:
        raise NotImplementedError()

    @abstractmethod
    def get_model(self) -> OpenapiModel:
        raise NotImplementedError()

    @abstractmethod
    def get_component_model(self) -> ComponentsModel:
        raise NotImplementedError()

    @abstractmethod
    def build_open_api_yaml(self) -> str:
        raise NotImplementedError()

    @abstractmethod
    def build_processor_params(
        self,
        route: Route,
        processor: Union[MessageProcessor, Type[MessageProcessor]]
    ) -> RouteBuildParams:
        raise NotImplementedError()

    @abstractmethod
    def build_schema_model(
        self,
        schema_type: Type,
        parameters: RouteBuildParams,
        path_model: Optional[PathModel] = None,
    ) -> SchemaModel:
        raise NotImplementedError()

    @abstractmethod
    def build_property_model(
        self,
        property_type: Type,
        parameters: RouteBuildParams,
        default=inspect.Signature.empty,
    ) -> SchemaModel:
        raise NotImplementedError()

    @abstractmethod
    def add_query_parameter(
        self,
        path_model: PathModel,
        parameter_type: type,
        parameter_name: str,
        required: bool = False,
        default=inspect.Signature.empty
    ):
        raise NotImplementedError()

    @abstractmethod
    def add_query_parameters(self, path_model: PathModel, request_type: Optional[Type] = None):
        raise NotImplementedError()

    @abstractmethod
    def add_request_body(self, parameters: RouteBuildParams, path_model: PathModel):
        raise NotImplementedError()

    @abstractmethod
    def add_response_body(self, parameters: RouteBuildParams, path_model: PathModel):
        raise NotImplementedError()

    @abstractmethod
    def add_path_parameters(self, route: Route, path_model: PathModel):
        raise NotImplementedError()
