# DO NOT EDIT THIS FILE!
#
# This file is generated from the CDP specification. If you need to make
# changes, edit the generator and regenerate all of the modules.
#
# CDP domain: PerformanceTimeline (experimental)

from __future__ import annotations
import typing
from dataclasses import dataclass
from .util import event_class, T_JSON_DICT
from . import dom
from . import network
from . import page


@dataclass
class LargestContentfulPaint:
    """
    See https://github.com/WICG/LargestContentfulPaint
    and largest_contentful_paint.idl
    """
    render_time: network.TimeSinceEpoch
    load_time: network.TimeSinceEpoch
    #: The number of pixels being painted.
    size: float
    #: The id attribute of the element, if available.
    element_id: typing.Optional[str] = None
    #: The URL of the image (may be trimmed).
    url: typing.Optional[str] = None
    node_id: typing.Optional[dom.BackendNodeId] = None

    def to_json(self) -> T_JSON_DICT:
        json: T_JSON_DICT = dict()
        json["renderTime"] = self.render_time.to_json()
        json["loadTime"] = self.load_time.to_json()
        json["size"] = self.size
        if self.element_id is not None:
            json["elementId"] = self.element_id
        if self.url is not None:
            json["url"] = self.url
        if self.node_id is not None:
            json["nodeId"] = self.node_id.to_json()
        return json

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> LargestContentfulPaint:
        return cls(
            render_time=network.TimeSinceEpoch.from_json(json["renderTime"]),
            load_time=network.TimeSinceEpoch.from_json(json["loadTime"]),
            size=float(json["size"]),
            element_id=(
                str(json["elementId"])
                if json.get("elementId", None) is not None
                else None
            ),
            url=(
                str(json["url"]) if json.get("url", None) is not None else None
            ),
            node_id=(
                dom.BackendNodeId.from_json(json["nodeId"])
                if json.get("nodeId", None) is not None
                else None
            ),
        )


@dataclass
class LayoutShiftAttribution:
    previous_rect: dom.Rect
    current_rect: dom.Rect
    node_id: typing.Optional[dom.BackendNodeId] = None

    def to_json(self) -> T_JSON_DICT:
        json: T_JSON_DICT = dict()
        json["previousRect"] = self.previous_rect.to_json()
        json["currentRect"] = self.current_rect.to_json()
        if self.node_id is not None:
            json["nodeId"] = self.node_id.to_json()
        return json

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> LayoutShiftAttribution:
        return cls(
            previous_rect=dom.Rect.from_json(json["previousRect"]),
            current_rect=dom.Rect.from_json(json["currentRect"]),
            node_id=(
                dom.BackendNodeId.from_json(json["nodeId"])
                if json.get("nodeId", None) is not None
                else None
            ),
        )


@dataclass
class LayoutShift:
    """
    See https://wicg.github.io/layout-instability/#sec-layout-shift
    and layout_shift.idl
    """
    #: Score increment produced by this event.
    value: float
    had_recent_input: bool
    last_input_time: network.TimeSinceEpoch
    sources: typing.List[LayoutShiftAttribution]

    def to_json(self) -> T_JSON_DICT:
        json: T_JSON_DICT = dict()
        json["value"] = self.value
        json["hadRecentInput"] = self.had_recent_input
        json["lastInputTime"] = self.last_input_time.to_json()
        json["sources"] = [i.to_json() for i in self.sources]
        return json

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> LayoutShift:
        return cls(
            value=float(json["value"]),
            had_recent_input=bool(json["hadRecentInput"]),
            last_input_time=network.TimeSinceEpoch.from_json(
                json["lastInputTime"]
            ),
            sources=[
                LayoutShiftAttribution.from_json(i) for i in json["sources"]
            ],
        )


@dataclass
class TimelineEvent:
    #: Identifies the frame that this event is related to.
    #: Empty for non-frame targets.
    frame_id: page.FrameId
    #: The event type, as specified in
    #: https://w3c.github.io/performance-timeline
    #: /#dom-performanceentry-entrytype
    #: This determines which of the optional "details" fields is present.
    type_: str
    #: Name may be empty depending on the type.
    name: str
    #: Time in seconds since Epoch,
    #: monotonically increasing within document lifetime.
    time: network.TimeSinceEpoch
    #: Event duration, if applicable.
    duration: typing.Optional[float] = None
    lcp_details: typing.Optional[LargestContentfulPaint] = None
    layout_shift_details: typing.Optional[LayoutShift] = None

    def to_json(self) -> T_JSON_DICT:
        json: T_JSON_DICT = dict()
        json["frameId"] = self.frame_id.to_json()
        json["type"] = self.type_
        json["name"] = self.name
        json["time"] = self.time.to_json()
        if self.duration is not None:
            json["duration"] = self.duration
        if self.lcp_details is not None:
            json["lcpDetails"] = self.lcp_details.to_json()
        if self.layout_shift_details is not None:
            json["layoutShiftDetails"] = self.layout_shift_details.to_json()
        return json

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> TimelineEvent:
        return cls(
            frame_id=page.FrameId.from_json(json["frameId"]),
            type_=str(json["type"]),
            name=str(json["name"]),
            time=network.TimeSinceEpoch.from_json(json["time"]),
            duration=(
                float(json["duration"])
                if json.get("duration", None) is not None
                else None
            ),
            lcp_details=(
                LargestContentfulPaint.from_json(json["lcpDetails"])
                if json.get("lcpDetails", None) is not None
                else None
            ),
            layout_shift_details=(
                LayoutShift.from_json(json["layoutShiftDetails"])
                if json.get("layoutShiftDetails", None) is not None
                else None
            ),
        )


def enable(
    event_types: typing.List[str],
) -> typing.Generator[T_JSON_DICT, T_JSON_DICT, None]:
    """
    Previously buffered events would be reported before method returns.
    See also: timelineEventAdded.
    :param event_types: The types of event to report, as specified in
    https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype
    The specified filter overrides any previous filters,
    passing empty filter disables recording.
    Note that not all types exposed to the web platform are currently supported
    """
    params: T_JSON_DICT = dict()
    params["eventTypes"] = [i for i in event_types]
    cmd_dict: T_JSON_DICT = {
        "method": "PerformanceTimeline.enable",
        "params": params,
    }
    json = yield cmd_dict  # noqa


@event_class("PerformanceTimeline.timelineEventAdded")
@dataclass
class TimelineEventAdded:
    """
    Sent when a performance timeline event is added.
    See reportPerformanceTimeline method.
    """
    event: TimelineEvent

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> TimelineEventAdded:
        return cls(event=TimelineEvent.from_json(json["event"]))
