from typing import Any, Dict, List, Optional, Type

from django.db import models
from django.forms import models as model_forms, Form  # type: ignore  # This will be solved when adding forms module
from django.http import HttpResponse, HttpRequest
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
from django.views.generic.detail import BaseDetailView, SingleObjectMixin, SingleObjectTemplateResponseMixin

class FormMixin(ContextMixin):
    initial = ...  # type: Dict[str, object]
    form_class = ...  # type: Optional[Type[Form]]
    success_url = ...  # type: Optional[str]
    prefix = ...  # type: Optional[str]
    request = ...  # type: HttpRequest
    def render_to_response(self, context: Dict[str, object], **response_kwargs: object) -> HttpResponse: ...
    def get_initial(self) -> Dict[str, object]: ...
    def get_prefix(self) -> Optional[str]: ...
    def get_form_class(self) -> Type[Form]: ...
    def get_form(self, form_class: Type[Form] = None) -> Form: ...
    def get_form_kwargs(self) -> Dict[str, Any]: ...
    def get_success_url(self) -> str: ...
    def form_valid(self, form: Form) -> HttpResponse: ...
    def form_invalid(self, form: Form) -> HttpResponse: ...
    def get_context_data(self, **kwargs: object) -> Dict[str, object]: ...

class ModelFormMixin(FormMixin, SingleObjectMixin):
    fields = ...  # type: Optional[List[str]]
    object = ...  # type: models.Model
    def get_form_class(self) -> Type[Form]: ...
    def get_form_kwargs(self) -> Dict[str, object]: ...
    def get_success_url(self) -> str: ...
    def form_valid(self, form: Form) -> HttpResponse: ...

class ProcessFormView(View):
    def render_to_response(self, context: Dict[str, object], **response_kwargs: object) -> HttpResponse: ...
    def get_context_data(self, **kwargs: object) -> Dict[str, object]: ...
    def get_form(self, form_class: Type[Form] = None) -> Form: ...
    def form_valid(self, form: Form) -> HttpResponse: ...
    def form_invalid(self, form: Form) -> HttpResponse: ...
    def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
    def put(self, *args: Any, **kwargs: Any) -> HttpResponse: ...

class BaseFormView(FormMixin, ProcessFormView): ...
class FormView(TemplateResponseMixin, BaseFormView): ...

class BaseCreateView(ModelFormMixin, ProcessFormView):
    object = ...  # type: models.Model
    def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...

class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
    template_name_suffix = ...  # type: str

class BaseUpdateView(ModelFormMixin, ProcessFormView):
    object = ...  # type: models.Model
    def get(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: object, **kwargs: object) -> HttpResponse: ...

class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
    template_name_suffix = ...  # type: str

_object = object

class DeletionMixin:
    success_url = ...  # type: Optional[str]
    object = ...  # type: models.Model
    def delete(self, request: HttpRequest, *args: _object, **kwargs: _object) -> HttpResponse: ...
    def post(self, request: HttpRequest, *args: _object, **kwargs: _object) -> HttpResponse: ...
    def get_success_url(self) -> str: ...

class BaseDeleteView(DeletionMixin, BaseDetailView): ...

class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView):
    template_name_suffix = ...  # type: str
