# generated by quicktype.io from ./trendy.json 
# TODO: use it - it's for future use now
# This code parses date/times, so please
#
#     pip install python-dateutil
#
# To use this code, make sure you
#
#     import json
#
# and then, to convert JSON from a string, do
#
#     result = cmc_trending_response_from_dict(json.loads(json_string))

from enum import Enum
from dataclasses import dataclass
from typing import Any, Optional, List, TypeVar, Type, cast, Callable
from datetime import datetime
import dateutil.parser


T = TypeVar("T")
EnumT = TypeVar("EnumT", bound=Enum)


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


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


def to_enum(c: Type[EnumT], x: Any) -> EnumT:
    assert isinstance(x, c)
    return x.value


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


def from_datetime(x: Any) -> datetime:
    return dateutil.parser.parse(x)


def from_none(x: Any) -> Any:
    assert x is None
    return x


def from_union(fs, x):
    for f in fs:
        try:
            return f(x)
        except:
            pass
    assert False


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]


class Name(Enum):
    APTOS = "Aptos"
    BNB = "BNB"
    ETHEREUM = "Ethereum"
    TRON = "TRON"


class Slug(Enum):
    APTOS = "aptos"
    BNB = "bnb"
    ETHEREUM = "ethereum"
    TRON = "tron"


class Symbol(Enum):
    APT = "APT"
    BNB = "BNB"
    ETH = "ETH"
    TRX = "TRX"


@dataclass
class Platform:
    id: int
    name: Name
    slug: Slug
    symbol: Symbol
    token_address: str

    @staticmethod
    def from_dict(obj: Any) -> 'Platform':
        assert isinstance(obj, dict)
        id = from_int(obj.get("id"))
        name = Name(obj.get("name"))
        slug = Slug(obj.get("slug"))
        symbol = Symbol(obj.get("symbol"))
        token_address = from_str(obj.get("token_address"))
        return Platform(id, name, slug, symbol, token_address)

    def to_dict(self) -> dict:
        result: dict = {}
        result["id"] = from_int(self.id)
        result["name"] = to_enum(Name, self.name)
        result["slug"] = to_enum(Slug, self.slug)
        result["symbol"] = to_enum(Symbol, self.symbol)
        result["token_address"] = from_str(self.token_address)
        return result


@dataclass
class Usd:
    fully_diluted_market_cap: float
    last_updated: datetime
    market_cap: float
    market_cap_dominance: float
    percent_change_1_h: float
    percent_change_24_h: float
    percent_change_30_d: float
    percent_change_60_d: float
    percent_change_7_d: float
    percent_change_90_d: float
    price: float
    volume_24_h: float
    volume_change_24_h: float
    tvl: Optional[float] = None

    @staticmethod
    def from_dict(obj: Any) -> 'Usd':
        assert isinstance(obj, dict)
        fully_diluted_market_cap = from_float(obj.get("fully_diluted_market_cap"))
        last_updated = from_datetime(obj.get("last_updated"))
        market_cap = from_float(obj.get("market_cap"))
        market_cap_dominance = from_float(obj.get("market_cap_dominance"))
        percent_change_1_h = from_float(obj.get("percent_change_1h"))
        percent_change_24_h = from_float(obj.get("percent_change_24h"))
        percent_change_30_d = from_float(obj.get("percent_change_30d"))
        percent_change_60_d = from_float(obj.get("percent_change_60d"))
        percent_change_7_d = from_float(obj.get("percent_change_7d"))
        percent_change_90_d = from_float(obj.get("percent_change_90d"))
        price = from_float(obj.get("price"))
        volume_24_h = from_float(obj.get("volume_24h"))
        volume_change_24_h = from_float(obj.get("volume_change_24h"))
        tvl = from_union([from_none, from_float], obj.get("tvl"))
        return Usd(fully_diluted_market_cap, last_updated, market_cap, market_cap_dominance, percent_change_1_h, percent_change_24_h, percent_change_30_d, percent_change_60_d, percent_change_7_d, percent_change_90_d, price, volume_24_h, volume_change_24_h, tvl)

    def to_dict(self) -> dict:
        result: dict = {}
        result["fully_diluted_market_cap"] = to_float(self.fully_diluted_market_cap)
        result["last_updated"] = self.last_updated.isoformat()
        result["market_cap"] = to_float(self.market_cap)
        result["market_cap_dominance"] = to_float(self.market_cap_dominance)
        result["percent_change_1h"] = to_float(self.percent_change_1_h)
        result["percent_change_24h"] = to_float(self.percent_change_24_h)
        result["percent_change_30d"] = to_float(self.percent_change_30_d)
        result["percent_change_60d"] = to_float(self.percent_change_60_d)
        result["percent_change_7d"] = to_float(self.percent_change_7_d)
        result["percent_change_90d"] = to_float(self.percent_change_90_d)
        result["price"] = to_float(self.price)
        result["volume_24h"] = to_float(self.volume_24_h)
        result["volume_change_24h"] = to_float(self.volume_change_24_h)
        result["tvl"] = from_union([from_none, to_float], self.tvl)
        return result


@dataclass
class Quote:
    usd: Usd

    @staticmethod
    def from_dict(obj: Any) -> 'Quote':
        assert isinstance(obj, dict)
        usd = Usd.from_dict(obj.get("USD"))
        return Quote(usd)

    def to_dict(self) -> dict:
        result: dict = {}
        result["USD"] = to_class(Usd, self.usd)
        return result


@dataclass
class CmcTrendingResponseElement:
    circulating_supply: float
    cmc_rank: int
    date_added: datetime
    id: int
    is_active: int
    is_fiat: int
    last_updated: datetime
    name: str
    num_market_pairs: int
    quote: Quote
    slug: str
    symbol: str
    tags: List[str]
    total_supply: float
    max_supply: Optional[int] = None
    platform: Optional[Platform] = None
    self_reported_circulating_supply: Optional[float] = None
    self_reported_market_cap: Optional[float] = None
    tvl_ratio: Optional[float] = None

    @staticmethod
    def from_dict(obj: Any) -> 'CmcTrendingResponseElement':
        assert isinstance(obj, dict)
        circulating_supply = from_float(obj.get("circulating_supply"))
        cmc_rank = from_int(obj.get("cmc_rank"))
        date_added = from_datetime(obj.get("date_added"))
        id = from_int(obj.get("id"))
        is_active = from_int(obj.get("is_active"))
        is_fiat = from_int(obj.get("is_fiat"))
        last_updated = from_datetime(obj.get("last_updated"))
        name = from_str(obj.get("name"))
        num_market_pairs = from_int(obj.get("num_market_pairs"))
        quote = Quote.from_dict(obj.get("quote"))
        slug = from_str(obj.get("slug"))
        symbol = from_str(obj.get("symbol"))
        tags = from_list(from_str, obj.get("tags"))
        total_supply = from_float(obj.get("total_supply"))
        max_supply = from_union([from_int, from_none], obj.get("max_supply"))
        platform = from_union([from_none, Platform.from_dict], obj.get("platform"))
        self_reported_circulating_supply = from_union([from_none, from_float], obj.get("self_reported_circulating_supply"))
        self_reported_market_cap = from_union([from_none, from_float], obj.get("self_reported_market_cap"))
        tvl_ratio = from_union([from_none, from_float], obj.get("tvl_ratio"))
        return CmcTrendingResponseElement(circulating_supply, cmc_rank, date_added, id, is_active, is_fiat, last_updated, name, num_market_pairs, quote, slug, symbol, tags, total_supply, max_supply, platform, self_reported_circulating_supply, self_reported_market_cap, tvl_ratio)

    def to_dict(self) -> dict:
        result: dict = {}
        result["circulating_supply"] = to_float(self.circulating_supply)
        result["cmc_rank"] = from_int(self.cmc_rank)
        result["date_added"] = self.date_added.isoformat()
        result["id"] = from_int(self.id)
        result["is_active"] = from_int(self.is_active)
        result["is_fiat"] = from_int(self.is_fiat)
        result["last_updated"] = self.last_updated.isoformat()
        result["name"] = from_str(self.name)
        result["num_market_pairs"] = from_int(self.num_market_pairs)
        result["quote"] = to_class(Quote, self.quote)
        result["slug"] = from_str(self.slug)
        result["symbol"] = from_str(self.symbol)
        result["tags"] = from_list(from_str, self.tags)
        result["total_supply"] = to_float(self.total_supply)
        result["max_supply"] = from_union([from_int, from_none], self.max_supply)
        result["platform"] = from_union([from_none, lambda x: to_class(Platform, x)], self.platform)
        result["self_reported_circulating_supply"] = from_union([from_none, to_float], self.self_reported_circulating_supply)
        result["self_reported_market_cap"] = from_union([from_none, to_float], self.self_reported_market_cap)
        result["tvl_ratio"] = from_union([from_none, to_float], self.tvl_ratio)
        return result


def cmc_trending_response_from_dict(s: Any) -> List[CmcTrendingResponseElement]:
    return from_list(CmcTrendingResponseElement.from_dict, s)


def cmc_trending_response_to_dict(x: List[CmcTrendingResponseElement]) -> Any:
    return from_list(lambda x: to_class(CmcTrendingResponseElement, x), x)
