from __future__ import annotations

from typing import TYPE_CHECKING, List

from twisted.web.iweb import ITemplateLoader
from twisted.web.template import Tag, renderer

from pydoctor.model import Function
from pydoctor.templatewriter import TemplateElement, util
from pydoctor.templatewriter.pages import format_decorators, format_function_def, format_overloads

if TYPE_CHECKING:
    from twisted.web.template import Flattenable


class FunctionChild(TemplateElement):

    filename = 'function-child.html'

    def __init__(self,
            docgetter: util.DocGetter,
            ob: Function,
            extras: List["Flattenable"],
            loader: ITemplateLoader
            ):
        super().__init__(loader)
        self.docgetter = docgetter
        self.ob = ob
        self._functionExtras = extras

    @renderer
    def class_(self, request: object, tag: Tag) -> "Flattenable":
        class_ = util.css_class(self.ob)
        if self.ob.parent is not self.ob:
            class_ = 'base' + class_
        return class_

    @renderer
    def functionAnchor(self, request: object, tag: Tag) -> "Flattenable":
        return self.ob.fullName()

    @renderer
    def shortFunctionAnchor(self, request: object, tag: Tag) -> str:
        return self.ob.name
    
    @renderer
    def anchorHref(self, request: object, tag: Tag) -> str:
        name = self.shortFunctionAnchor(request, tag)
        return f'#{name}'

    @renderer
    def overloads(self, request: object, tag: Tag) -> "Flattenable":
        return list(format_overloads(self.ob))

    @renderer
    def decorator(self, request: object, tag: Tag) -> "Flattenable":
        return format_decorators(self.ob)

    @renderer
    def functionDef(self, request: object, tag: Tag) -> "Flattenable":
        return format_function_def(self.ob.name, self.ob.is_async, self.ob)

    @renderer
    def sourceLink(self, request: object, tag: Tag) -> "Flattenable":
        if self.ob.source_href:
            return tag.fillSlots(sourceHref=self.ob.source_href)
        else:
            return ()

    @renderer
    def objectExtras(self, request: object, tag: Tag) -> List["Flattenable"]:
        return self._functionExtras

    @renderer
    def functionBody(self, request: object, tag: Tag) -> "Flattenable":
        return self.docgetter.get(self.ob)

