from typing import Any, List, Dict, TypeVar, Type, cast, Callable


T = TypeVar("T")


def from_bool(x: Any) -> bool:
    assert isinstance(x, bool)
    return x


def from_str(x: Any) -> str:
    assert isinstance(x, str)
    return x


def from_float(x: Any) -> float:
    assert isinstance(x, (float, int)) and not isinstance(x, bool)
    return float(x)


def from_int(x: Any) -> int:
    assert isinstance(x, int) and not isinstance(x, bool)
    return x


def to_float(x: Any) -> float:
    assert isinstance(x, float)
    return x


def to_class(c: Type[T], x: Any) -> dict:
    assert isinstance(x, c)
    return cast(Any, x).to_dict()


def from_list(f: Callable[[Any], T], x: Any) -> List[T]:
    assert isinstance(x, list)
    return [f(y) for y in x]


def from_dict(f: Callable[[Any], T], x: Any) -> Dict[str, T]:
    assert isinstance(x, dict)
    return { k: f(v) for (k, v) in x.items() }


class Attributes:
    autoplay: bool
    controls: bool
    loop: bool
    muted: bool
    playsinline: bool

    def __init__(self, autoplay: bool, controls: bool, loop: bool, muted: bool, playsinline: bool) -> None:
        self.autoplay = autoplay
        self.controls = controls
        self.loop = loop
        self.muted = muted
        self.playsinline = playsinline

    @staticmethod
    def from_dict(obj: Any) -> 'Attributes':
        assert isinstance(obj, dict)
        autoplay = from_bool(obj.get("autoplay"))
        controls = from_bool(obj.get("controls"))
        loop = from_bool(obj.get("loop"))
        muted = from_bool(obj.get("muted"))
        playsinline = from_bool(obj.get("playsinline"))
        return Attributes(autoplay, controls, loop, muted, playsinline)

    def to_dict(self) -> dict:
        result: dict = {}
        result["autoplay"] = from_bool(self.autoplay)
        result["controls"] = from_bool(self.controls)
        result["loop"] = from_bool(self.loop)
        result["muted"] = from_bool(self.muted)
        result["playsinline"] = from_bool(self.playsinline)
        return result


class Colors:
    primary: str
    secondary: str
    tertiary: str

    def __init__(self, primary: str, secondary: str, tertiary: str) -> None:
        self.primary = primary
        self.secondary = secondary
        self.tertiary = tertiary

    @staticmethod
    def from_dict(obj: Any) -> 'Colors':
        assert isinstance(obj, dict)
        primary = from_str(obj.get("primary"))
        secondary = from_str(obj.get("secondary"))
        tertiary = from_str(obj.get("tertiary"))
        return Colors(primary, secondary, tertiary)

    def to_dict(self) -> dict:
        result: dict = {}
        result["primary"] = from_str(self.primary)
        result["secondary"] = from_str(self.secondary)
        result["tertiary"] = from_str(self.tertiary)
        return result


class Dimensions:
    aspect_ratio: float
    height: int
    width: int

    def __init__(self, aspect_ratio: float, height: int, width: int) -> None:
        self.aspect_ratio = aspect_ratio
        self.height = height
        self.width = width

    @staticmethod
    def from_dict(obj: Any) -> 'Dimensions':
        assert isinstance(obj, dict)
        aspect_ratio = from_float(obj.get("aspectRatio"))
        height = from_int(obj.get("height"))
        width = from_int(obj.get("width"))
        return Dimensions(aspect_ratio, height, width)

    def to_dict(self) -> dict:
        result: dict = {}
        result["aspectRatio"] = to_float(self.aspect_ratio)
        result["height"] = from_int(self.height)
        result["width"] = from_int(self.width)
        return result


class Thumbnails:
    pass

    def __init__(self, ) -> None:
        pass

    @staticmethod
    def from_dict(obj: Any) -> 'Thumbnails':
        assert isinstance(obj, dict)
        return Thumbnails()

    def to_dict(self) -> dict:
        result: dict = {}
        return result


class BlockElement:
    alt: str
    analyzed: bool
    anchor: str
    attributes: Attributes
    caption: str
    colors: Colors
    content: str
    content_type: str
    dimensions: Dimensions
    dist_source: str
    duration: float
    has_sound: bool
    id: str
    index: int
    online: bool
    relative_source: str
    size: int
    text: str
    thumbnails: Thumbnails
    thumbnails_built_at: str
    title: str
    type: str
    url: str

    def __init__(self, alt: str, analyzed: bool, anchor: str, attributes: Attributes, caption: str, colors: Colors, content: str, content_type: str, dimensions: Dimensions, dist_source: str, duration: float, has_sound: bool, id: str, index: int, online: bool, relative_source: str, size: int, text: str, thumbnails: Thumbnails, thumbnails_built_at: str, title: str, type: str, url: str) -> None:
        self.alt = alt
        self.analyzed = analyzed
        self.anchor = anchor
        self.attributes = attributes
        self.caption = caption
        self.colors = colors
        self.content = content
        self.content_type = content_type
        self.dimensions = dimensions
        self.dist_source = dist_source
        self.duration = duration
        self.has_sound = has_sound
        self.id = id
        self.index = index
        self.online = online
        self.relative_source = relative_source
        self.size = size
        self.text = text
        self.thumbnails = thumbnails
        self.thumbnails_built_at = thumbnails_built_at
        self.title = title
        self.type = type
        self.url = url

    @staticmethod
    def from_dict(obj: Any) -> 'BlockElement':
        assert isinstance(obj, dict)
        alt = from_str(obj.get("alt"))
        analyzed = from_bool(obj.get("analyzed"))
        anchor = from_str(obj.get("anchor"))
        attributes = Attributes.from_dict(obj.get("attributes"))
        caption = from_str(obj.get("caption"))
        colors = Colors.from_dict(obj.get("colors"))
        content = from_str(obj.get("content"))
        content_type = from_str(obj.get("contentType"))
        dimensions = Dimensions.from_dict(obj.get("dimensions"))
        dist_source = from_str(obj.get("distSource"))
        duration = from_float(obj.get("duration"))
        has_sound = from_bool(obj.get("hasSound"))
        id = from_str(obj.get("id"))
        index = from_int(obj.get("index"))
        online = from_bool(obj.get("online"))
        relative_source = from_str(obj.get("relativeSource"))
        size = from_int(obj.get("size"))
        text = from_str(obj.get("text"))
        thumbnails = Thumbnails.from_dict(obj.get("thumbnails"))
        thumbnails_built_at = from_str(obj.get("thumbnailsBuiltAt"))
        title = from_str(obj.get("title"))
        type = from_str(obj.get("type"))
        url = from_str(obj.get("url"))
        return BlockElement(alt, analyzed, anchor, attributes, caption, colors, content, content_type, dimensions, dist_source, duration, has_sound, id, index, online, relative_source, size, text, thumbnails, thumbnails_built_at, title, type, url)

    def to_dict(self) -> dict:
        result: dict = {}
        result["alt"] = from_str(self.alt)
        result["analyzed"] = from_bool(self.analyzed)
        result["anchor"] = from_str(self.anchor)
        result["attributes"] = to_class(Attributes, self.attributes)
        result["caption"] = from_str(self.caption)
        result["colors"] = to_class(Colors, self.colors)
        result["content"] = from_str(self.content)
        result["contentType"] = from_str(self.content_type)
        result["dimensions"] = to_class(Dimensions, self.dimensions)
        result["distSource"] = from_str(self.dist_source)
        result["duration"] = to_float(self.duration)
        result["hasSound"] = from_bool(self.has_sound)
        result["id"] = from_str(self.id)
        result["index"] = from_int(self.index)
        result["online"] = from_bool(self.online)
        result["relativeSource"] = from_str(self.relative_source)
        result["size"] = from_int(self.size)
        result["text"] = from_str(self.text)
        result["thumbnails"] = to_class(Thumbnails, self.thumbnails)
        result["thumbnailsBuiltAt"] = from_str(self.thumbnails_built_at)
        result["title"] = from_str(self.title)
        result["type"] = from_str(self.type)
        result["url"] = from_str(self.url)
        return result


class ContentValue:
    blocks: List[BlockElement]
    footnotes: Dict[str, str]
    layout: List[List[str]]
    title: str

    def __init__(self, blocks: List[BlockElement], footnotes: Dict[str, str], layout: List[List[str]], title: str) -> None:
        self.blocks = blocks
        self.footnotes = footnotes
        self.layout = layout
        self.title = title

    @staticmethod
    def from_dict(obj: Any) -> 'ContentValue':
        assert isinstance(obj, dict)
        blocks = from_list(BlockElement.from_dict, obj.get("blocks"))
        footnotes = from_dict(from_str, obj.get("footnotes"))
        layout = from_list(lambda x: from_list(from_str, x), obj.get("layout"))
        title = from_str(obj.get("title"))
        return ContentValue(blocks, footnotes, layout, title)

    def to_dict(self) -> dict:
        result: dict = {}
        result["blocks"] = from_list(lambda x: to_class(BlockElement, x), self.blocks)
        result["footnotes"] = from_dict(from_str, self.footnotes)
        result["layout"] = from_list(lambda x: from_list(from_str, x), self.layout)
        result["title"] = from_str(self.title)
        return result


class DatabaseMetadataClass:
    partial: bool

    def __init__(self, partial: bool) -> None:
        self.partial = partial

    @staticmethod
    def from_dict(obj: Any) -> 'DatabaseMetadataClass':
        assert isinstance(obj, dict)
        partial = from_bool(obj.get("Partial"))
        return DatabaseMetadataClass(partial)

    def to_dict(self) -> dict:
        result: dict = {}
        result["Partial"] = from_bool(self.partial)
        return result


class Metadata:
    additional_metadata: Dict[str, Any]
    aliases: List[str]
    colors: Colors
    database_metadata: DatabaseMetadataClass
    finished: str
    made_with: List[str]
    page_background: str
    private: bool
    started: str
    tags: List[str]
    thumbnail: str
    title_style: str
    wip: bool

    def __init__(self, additional_metadata: Dict[str, Any], aliases: List[str], colors: Colors, database_metadata: DatabaseMetadataClass, finished: str, made_with: List[str], page_background: str, private: bool, started: str, tags: List[str], thumbnail: str, title_style: str, wip: bool) -> None:
        self.additional_metadata = additional_metadata
        self.aliases = aliases
        self.colors = colors
        self.database_metadata = database_metadata
        self.finished = finished
        self.made_with = made_with
        self.page_background = page_background
        self.private = private
        self.started = started
        self.tags = tags
        self.thumbnail = thumbnail
        self.title_style = title_style
        self.wip = wip

    @staticmethod
    def from_dict(obj: Any) -> 'Metadata':
        assert isinstance(obj, dict)
        additional_metadata = from_dict(lambda x: x, obj.get("additionalMetadata"))
        aliases = from_list(from_str, obj.get("aliases"))
        colors = Colors.from_dict(obj.get("colors"))
        database_metadata = DatabaseMetadataClass.from_dict(obj.get("databaseMetadata"))
        finished = from_str(obj.get("finished"))
        made_with = from_list(from_str, obj.get("madeWith"))
        page_background = from_str(obj.get("pageBackground"))
        private = from_bool(obj.get("private"))
        started = from_str(obj.get("started"))
        tags = from_list(from_str, obj.get("tags"))
        thumbnail = from_str(obj.get("thumbnail"))
        title_style = from_str(obj.get("titleStyle"))
        wip = from_bool(obj.get("wip"))
        return Metadata(additional_metadata, aliases, colors, database_metadata, finished, made_with, page_background, private, started, tags, thumbnail, title_style, wip)

    def to_dict(self) -> dict:
        result: dict = {}
        result["additionalMetadata"] = from_dict(lambda x: x, self.additional_metadata)
        result["aliases"] = from_list(from_str, self.aliases)
        result["colors"] = to_class(Colors, self.colors)
        result["databaseMetadata"] = to_class(DatabaseMetadataClass, self.database_metadata)
        result["finished"] = from_str(self.finished)
        result["madeWith"] = from_list(from_str, self.made_with)
        result["pageBackground"] = from_str(self.page_background)
        result["private"] = from_bool(self.private)
        result["started"] = from_str(self.started)
        result["tags"] = from_list(from_str, self.tags)
        result["thumbnail"] = from_str(self.thumbnail)
        result["titleStyle"] = from_str(self.title_style)
        result["wip"] = from_bool(self.wip)
        return result


class DatabaseValue:
    built_at: str
    content: Dict[str, ContentValue]
    description_hash: str
    id: str
    metadata: Metadata
    partial: bool

    def __init__(self, built_at: str, content: Dict[str, ContentValue], description_hash: str, id: str, metadata: Metadata, partial: bool) -> None:
        self.built_at = built_at
        self.content = content
        self.description_hash = description_hash
        self.id = id
        self.metadata = metadata
        self.partial = partial

    @staticmethod
    def from_dict(obj: Any) -> 'DatabaseValue':
        assert isinstance(obj, dict)
        built_at = from_str(obj.get("builtAt"))
        content = from_dict(ContentValue.from_dict, obj.get("content"))
        description_hash = from_str(obj.get("descriptionHash"))
        id = from_str(obj.get("id"))
        metadata = Metadata.from_dict(obj.get("metadata"))
        partial = from_bool(obj.get("Partial"))
        return DatabaseValue(built_at, content, description_hash, id, metadata, partial)

    def to_dict(self) -> dict:
        result: dict = {}
        result["builtAt"] = from_str(self.built_at)
        result["content"] = from_dict(lambda x: to_class(ContentValue, x), self.content)
        result["descriptionHash"] = from_str(self.description_hash)
        result["id"] = from_str(self.id)
        result["metadata"] = to_class(Metadata, self.metadata)
        result["Partial"] = from_bool(self.partial)
        return result


def database_from_dict(s: Any) -> Dict[str, DatabaseValue]:
    return from_dict(DatabaseValue.from_dict, s)


def database_to_dict(x: Dict[str, DatabaseValue]) -> Any:
    return from_dict(lambda x: to_class(DatabaseValue, x), x)
