# generated by datamodel-codegen:
#   filename:  Marketdata/Candle.json

from __future__ import annotations
from datetime import datetime, timezone

from decimal import Decimal
from typing import Annotated, Optional

from msgspec import Meta, Struct

from .. import definitions


class Candle(Struct, omit_defaults=True):
    av: Annotated[Decimal, Meta(title="sell_volume")]
    bv: Annotated[Decimal, Meta(title="buy_volume")]
    s: Annotated[str, Meta(title="symbol")]
    tn: Annotated[int, Meta(ge=0, title="timestamp_ns")]
    ts: Annotated[int, Meta(title="timestamp")]
    v: Annotated[Decimal, Meta(title="volume")]
    w: Annotated[definitions.CandleWidth, Meta(title="width")]
    ac: Optional[Annotated[Optional[Decimal], Meta(title="ask_close")]] = None
    ah: Optional[Annotated[Optional[Decimal], Meta(title="ask_high")]] = None
    al: Optional[Annotated[Optional[Decimal], Meta(title="ask_low")]] = None
    ao: Optional[Annotated[Optional[Decimal], Meta(title="ask_open")]] = None
    bc: Optional[Annotated[Optional[Decimal], Meta(title="bid_close")]] = None
    bh: Optional[Annotated[Optional[Decimal], Meta(title="bid_high")]] = None
    bl: Optional[Annotated[Optional[Decimal], Meta(title="bid_low")]] = None
    bo: Optional[Annotated[Optional[Decimal], Meta(title="bid_open")]] = None
    c: Optional[Annotated[Optional[Decimal], Meta(title="close")]] = None
    h: Optional[Annotated[Optional[Decimal], Meta(title="high")]] = None
    l: Optional[Annotated[Optional[Decimal], Meta(title="low")]] = None
    mc: Optional[Annotated[Optional[Decimal], Meta(title="mid_close")]] = None
    mh: Optional[Annotated[Optional[Decimal], Meta(title="mid_high")]] = None
    ml: Optional[Annotated[Optional[Decimal], Meta(title="mid_low")]] = None
    mo: Optional[Annotated[Optional[Decimal], Meta(title="mid_open")]] = None
    o: Optional[Annotated[Optional[Decimal], Meta(title="open")]] = None

    # Constructor that takes all field titles as arguments for convenience
    @classmethod
    def new(
        cls,
        sell_volume: Decimal,
        buy_volume: Decimal,
        symbol: str,
        timestamp_ns: int,
        timestamp: int,
        volume: Decimal,
        width: definitions.CandleWidth,
        ask_close: Optional[Decimal] = None,
        ask_high: Optional[Decimal] = None,
        ask_low: Optional[Decimal] = None,
        ask_open: Optional[Decimal] = None,
        bid_close: Optional[Decimal] = None,
        bid_high: Optional[Decimal] = None,
        bid_low: Optional[Decimal] = None,
        bid_open: Optional[Decimal] = None,
        close: Optional[Decimal] = None,
        high: Optional[Decimal] = None,
        low: Optional[Decimal] = None,
        mid_close: Optional[Decimal] = None,
        mid_high: Optional[Decimal] = None,
        mid_low: Optional[Decimal] = None,
        mid_open: Optional[Decimal] = None,
        open: Optional[Decimal] = None,
    ):
        return cls(
            sell_volume,
            buy_volume,
            symbol,
            timestamp_ns,
            timestamp,
            volume,
            width,
            ask_close,
            ask_high,
            ask_low,
            ask_open,
            bid_close,
            bid_high,
            bid_low,
            bid_open,
            close,
            high,
            low,
            mid_close,
            mid_high,
            mid_low,
            mid_open,
            open,
        )

    def __str__(self) -> str:
        return f"Candle(sell_volume={self.av},buy_volume={self.bv},symbol={self.s},timestamp_ns={self.tn},timestamp={self.ts},volume={self.v},width={self.w},ask_close={self.ac},ask_high={self.ah},ask_low={self.al},ask_open={self.ao},bid_close={self.bc},bid_high={self.bh},bid_low={self.bl},bid_open={self.bo},close={self.c},high={self.h},low={self.l},mid_close={self.mc},mid_high={self.mh},mid_low={self.ml},mid_open={self.mo},open={self.o})"

    @property
    def sell_volume(self) -> Decimal:
        return self.av

    @sell_volume.setter
    def sell_volume(self, value: Decimal) -> None:
        self.av = value

    @property
    def buy_volume(self) -> Decimal:
        return self.bv

    @buy_volume.setter
    def buy_volume(self, value: Decimal) -> None:
        self.bv = value

    @property
    def symbol(self) -> str:
        return self.s

    @symbol.setter
    def symbol(self, value: str) -> None:
        self.s = value

    @property
    def timestamp_ns(self) -> int:
        return self.tn

    @timestamp_ns.setter
    def timestamp_ns(self, value: int) -> None:
        self.tn = value

    @property
    def timestamp(self) -> int:
        return self.ts

    @timestamp.setter
    def timestamp(self, value: int) -> None:
        self.ts = value

    @property
    def datetime(self) -> datetime:
        """
        Convenience property to get the timestamp as a datetime object in UTC.
        """
        return datetime.fromtimestamp(self.ts, tz=timezone.utc)

    @property
    def datetime_local(self) -> datetime:
        """
        Convenience property to get the timestamp as a datetime object in local time.
        """
        return datetime.fromtimestamp(self.ts)

    @property
    def volume(self) -> Decimal:
        return self.v

    @volume.setter
    def volume(self, value: Decimal) -> None:
        self.v = value

    @property
    def width(self) -> definitions.CandleWidth:
        return self.w

    @width.setter
    def width(self, value: definitions.CandleWidth) -> None:
        self.w = value

    @property
    def ask_close(self) -> Optional[Decimal]:
        return self.ac

    @ask_close.setter
    def ask_close(self, value: Optional[Decimal]) -> None:
        self.ac = value

    @property
    def ask_high(self) -> Optional[Decimal]:
        return self.ah

    @ask_high.setter
    def ask_high(self, value: Optional[Decimal]) -> None:
        self.ah = value

    @property
    def ask_low(self) -> Optional[Decimal]:
        return self.al

    @ask_low.setter
    def ask_low(self, value: Optional[Decimal]) -> None:
        self.al = value

    @property
    def ask_open(self) -> Optional[Decimal]:
        return self.ao

    @ask_open.setter
    def ask_open(self, value: Optional[Decimal]) -> None:
        self.ao = value

    @property
    def bid_close(self) -> Optional[Decimal]:
        return self.bc

    @bid_close.setter
    def bid_close(self, value: Optional[Decimal]) -> None:
        self.bc = value

    @property
    def bid_high(self) -> Optional[Decimal]:
        return self.bh

    @bid_high.setter
    def bid_high(self, value: Optional[Decimal]) -> None:
        self.bh = value

    @property
    def bid_low(self) -> Optional[Decimal]:
        return self.bl

    @bid_low.setter
    def bid_low(self, value: Optional[Decimal]) -> None:
        self.bl = value

    @property
    def bid_open(self) -> Optional[Decimal]:
        return self.bo

    @bid_open.setter
    def bid_open(self, value: Optional[Decimal]) -> None:
        self.bo = value

    @property
    def close(self) -> Optional[Decimal]:
        return self.c

    @close.setter
    def close(self, value: Optional[Decimal]) -> None:
        self.c = value

    @property
    def high(self) -> Optional[Decimal]:
        return self.h

    @high.setter
    def high(self, value: Optional[Decimal]) -> None:
        self.h = value

    @property
    def low(self) -> Optional[Decimal]:
        return self.l

    @low.setter
    def low(self, value: Optional[Decimal]) -> None:
        self.l = value

    @property
    def mid_close(self) -> Optional[Decimal]:
        return self.mc

    @mid_close.setter
    def mid_close(self, value: Optional[Decimal]) -> None:
        self.mc = value

    @property
    def mid_high(self) -> Optional[Decimal]:
        return self.mh

    @mid_high.setter
    def mid_high(self, value: Optional[Decimal]) -> None:
        self.mh = value

    @property
    def mid_low(self) -> Optional[Decimal]:
        return self.ml

    @mid_low.setter
    def mid_low(self, value: Optional[Decimal]) -> None:
        self.ml = value

    @property
    def mid_open(self) -> Optional[Decimal]:
        return self.mo

    @mid_open.setter
    def mid_open(self, value: Optional[Decimal]) -> None:
        self.mo = value

    @property
    def open(self) -> Optional[Decimal]:
        return self.o

    @open.setter
    def open(self, value: Optional[Decimal]) -> None:
        self.o = value
