##############################################################################
#
#                        Crossbar.io Database
#     Copyright (c) typedef int GmbH. Licensed under MIT.
#
##############################################################################

import pprint
import uuid

import numpy as np
from txaio import time_ns
from zlmdb import flatbuffers

from cfxdb.gen.log import MWorkerLog as MWorkerLogGen


class _MWorkerLogGen(MWorkerLogGen.MWorkerLog):
    """
    Expand methods on the class code generated by flatc.

    FIXME: come up with a PR for flatc to generated this stuff automatically.
    """

    @classmethod
    def GetRootAsMWorkerLog(cls, buf, offset):
        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
        x = _MWorkerLogGen()
        x.Init(buf, n + offset)
        return x

    def NodeIdAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off : _off + _len]
        return None

    def MrealmIdAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off : _off + _len]
        return None


class MWorkerLog(object):
    WORKER_TYPES = {
        "": 0,
        "router": 1,
        "container": 2,
        "guest": 3,
        "testee": 4,
        "proxy": 5,
        "xbrmm": 6,
        "hostmonitor": 7,
        "controller": 8,
    }
    WORKER_TYPENAMES = {
        0: "",
        1: "router",
        2: "container",
        3: "guest",
        4: "testee",
        5: "proxy",
        6: "xbrmm",
        7: "hostmonitor",
        8: "controller",
    }

    def __init__(self, from_fbs=None):
        self._from_fbs = from_fbs

        # PK uint64
        self._timestamp = None

        # PK node_id: [uint8] (uuid);
        self._node_id = None

        # PK worker_id: string;
        self._worker_id = None

        # period: uint32;
        self._period = None

        # mrealm_id: [uint8] (uuid);
        self._mrealm_id = None

        # _type: MWorkerType;
        self._type = None

        # state: MWorkerState;
        self._state = None

        # sent: uint64;
        self._sent = None

        # seq: uint64;
        self._seq = None

        # num_fds: uint32;
        self._num_fds = None

        # num_threads: uint16;
        self._num_threads = None

        # num_ctx_switches_involuntary: uint64;
        self._num_ctx_switches_involuntary = None

        # num_ctx_switches_involuntary_per_sec: uint32;
        self._num_ctx_switches_involuntary_per_sec = None

        # num_ctx_switches_voluntary: uint64;
        self._num_ctx_switches_voluntary = None

        # num_ctx_switches_voluntary_per_sec: uint32;
        self._num_ctx_switches_voluntary_per_sec = None

        # cpu_system: float;
        self._cpu_system = None

        # cpu_system_per_sec: float;
        self._cpu_system_per_sec = None

        # cpu_wait: float;
        self._cpu_wait = None

        # cpu_wait_per_sec: float;
        self._cpu_wait_per_sec = None

        # cpu_user: float;
        self._cpu_user = None

        # cpu_user_per_sec: float;
        self._cpu_user_per_sec = None

        # read_bytes: uint64;
        self._read_bytes = None

        # read_bytes_per_sec: uint64;
        self._read_bytes_per_sec = None

        # read_ios: uint64;
        self._read_ios = None

        # read_ios_per_sec: uint64;
        self._read_ios_per_sec = None

        # write_bytes: uint64;
        self._write_bytes = None

        # write_bytes_per_sec: uint64;
        self._write_bytes_per_sec = None

        # write_ios: uint64;
        self._write_ios = None

        # write_ios_per_sec: uint64;
        self._write_ios_per_sec = None

        # sent_bytes: uint64;
        self._sent_bytes = None

        # sent_bytes_per_sec: uint64;
        self._sent_bytes_per_sec = None

        # sent_ios: uint64;
        self._sent_ios = None

        # sent_ios_per_sec: uint64;
        self._sent_ios_per_sec = None

        # recv_bytes: uint64;
        self._recv_bytes = None

        # recv_bytes_per_sec: uint64;
        self._recv_bytes_per_sec = None

        # recv_ios: uint64;
        self._recv_ios = None

        # recv_ios_per_sec: uint64;
        self._recv_ios_per_sec = None

        # router_roles: uint64;
        self._router_roles = None

        # router_sessions: uint64;
        self._router_sessions = None

        # recv_call: uint64;
        self._recv_call = None

        # recv_yield: uint64;
        self._recv_yield = None

        # sent_invocation: uint64;
        self._sent_invocation = None

        # sent_result: uint64;
        self._sent_result = None

        # recv_publish: uint64;
        self._recv_publish = None

        # sent_published: uint64;
        self._sent_published = None

        # sent_event: uint64;
        self._sent_event = None

        # recv_register: uint64;
        self._recv_register = None

        # sent_registered: uint64;
        self._sent_registered = None

        # recv_subscribe: uint64;
        self._recv_subscribe = None

        # sent_subscribed: uint64;
        self._sent_subscribed = None

    @staticmethod
    def parse(mrealm_id, node_id, worker_id, heartbeat):
        assert isinstance(mrealm_id, uuid.UUID)
        assert isinstance(node_id, uuid.UUID)
        assert type(worker_id) == str
        assert type(heartbeat) == dict
        assert "timestamp" in heartbeat and type(heartbeat["timestamp"]) == int
        assert "seq" in heartbeat and type(heartbeat["seq"]) == int
        assert "type" in heartbeat and type(heartbeat["type"]) == str

        obj = MWorkerLog()
        obj._timestamp = np.datetime64(time_ns(), "ns")
        obj._period = heartbeat.get("period", None)
        obj._mrealm_id = mrealm_id
        obj._node_id = node_id
        obj._worker_id = worker_id
        obj._sent = np.datetime64(heartbeat["timestamp"], "ns") if heartbeat.get("timestamp", None) else None
        obj._seq = heartbeat.get("seq", None)
        obj._type = MWorkerLog.WORKER_TYPES.get(heartbeat.get("type", None), None)
        obj._state = heartbeat.get("state", None)

        process = heartbeat.get("process", {})
        obj._num_fds = process.get("num_fds", 0)
        obj._num_threads = process.get("num_threads", 0)
        obj._num_ctx_switches_involuntary = process.get("num_ctx_switches_involuntary", 0)
        obj._num_ctx_switches_involuntary_per_sec = process.get("num_ctx_switches_involuntary_per_sec", 0)
        obj._num_ctx_switches_voluntary = process.get("num_ctx_switches_voluntary", 0)
        obj._num_ctx_switches_voluntary_per_sec = process.get("num_ctx_switches_voluntary_per_sec", 0)
        obj._cpu_system = process.get("cpu_system", 0)
        obj._cpu_system_per_sec = process.get("cpu_system_per_sec", 0)
        obj._cpu_wait = process.get("cpu_wait", 0)
        obj._cpu_wait_per_sec = process.get("cpu_wait_per_sec", 0)
        obj._cpu_user = process.get("cpu_user", 0)
        obj._cpu_user_per_sec = process.get("cpu_user_per_sec", 0)
        obj._read_bytes = process.get("read_bytes", 0)
        obj._read_bytes_per_sec = process.get("read_bytes_per_sec", 0)
        obj._read_ios = process.get("read_ios", 0)
        obj._read_ios_per_sec = process.get("read_ios_per_sec", 0)
        obj._write_bytes = process.get("write_bytes", 0)
        obj._write_bytes_per_sec = process.get("write_bytes_per_sec", 0)
        obj._write_bytes_per_sec = process.get("write_bytes_per_sec", 0)
        obj._write_ios_per_sec = process.get("write_ios_per_sec", 0)
        obj._sent_bytes = process.get("sent_bytes", 0)
        obj._sent_bytes_per_sec = process.get("sent_bytes_per_sec", 0)
        obj._sent_ios = process.get("sent_ios", 0)
        obj._sent_ios_per_sec = process.get("sent_ios_per_sec", 0)
        obj._recv_bytes = process.get("recv_bytes", 0)
        obj._recv_bytes_per_sec = process.get("recv_bytes_per_sec", 0)
        obj._recv_ios = process.get("recv_ios", 0)
        obj._recv_ios_per_sec = process.get("recv_ios_per_sec", 0)

        router = heartbeat.get("router", {})
        obj._router_roles = router.get("roles", 0)
        obj._router_sessions = router.get("sessions", 0)

        messages = router.get("messages", {})
        obj._recv_call = messages.get("call", 0)
        obj._recv_yield = messages.get("yield", 0)
        obj._sent_invocation = messages.get("invocation", 0)
        obj._sent_result = messages.get("result", 0)
        obj._recv_publish = messages.get("publish", 0)
        obj._sent_published = messages.get("published", 0)
        obj._sent_event = messages.get("event", 0)
        obj._recv_register = messages.get("register", 0)
        obj._sent_registered = messages.get("registered", 0)
        obj._recv_subscribe = messages.get("subscribe", 0)
        obj._sent_subscribed = messages.get("subscribed", 0)

        return obj

    def marshal(self):
        obj = {
            "timestamp": int(self.timestamp) if self.timestamp else None,
            "period": self.period,
            "mrealm_id": str(self.mrealm_id) if self.mrealm_id else None,
            "node_id": str(self.node_id) if self.node_id else None,
            "worker_id": self.worker_id,
            "sent": int(self.sent) if self.sent else None,
            "seq": self.seq,
            "type": MWorkerLog.WORKER_TYPENAMES.get(self.type, None),
            "state": self.state,
            "process": {
                "num_fds": self.num_fds,
                "num_threads": self.num_threads,
                "num_ctx_switches_involuntary": self.num_ctx_switches_involuntary,
                "num_ctx_switches_involuntary_per_sec": self.num_ctx_switches_involuntary_per_sec,
                "num_ctx_switches_voluntary": self.num_ctx_switches_voluntary,
                "num_ctx_switches_voluntary_per_sec": self.num_ctx_switches_voluntary_per_sec,
                "cpu_system": self.cpu_system,
                "cpu_system_per_sec": self.cpu_system_per_sec,
                "cpu_wait": self.cpu_wait,
                "cpu_wait_per_sec": self.cpu_wait_per_sec,
                "cpu_user": self.cpu_user,
                "cpu_user_per_sec": self.cpu_user_per_sec,
                "read_bytes": self.read_bytes,
                "read_bytes_per_sec": self.read_bytes_per_sec,
                "read_ios": self.read_ios,
                "read_ios_per_sec": self.read_ios_per_sec,
                "write_bytes": self.write_bytes,
                "write_bytes_per_sec": self.write_bytes_per_sec,
                "write_ios": self.write_ios,
                "write_ios_per_sec": self.write_ios_per_sec,
                "sent_bytes": self.sent_bytes,
                "sent_bytes_per_sec": self.sent_bytes_per_sec,
                "sent_ios": self.sent_ios,
                "sent_ios_per_sec": self.sent_ios_per_sec,
                "recv_bytes": self.recv_bytes,
                "recv_bytes_per_sec": self.recv_bytes_per_sec,
                "recv_ios": self.recv_ios,
                "recv_ios_per_sec": self.recv_ios_per_sec,
            },
        }
        if self.type == 1:
            obj["router"] = {
                "roles": self.router_roles,
                "sessions": self.router_sessions,
                "messages": {
                    "call": self.recv_call,
                    "yield": self.recv_yield,
                    "invocation": self.sent_invocation,
                    "result": self.sent_result,
                    "publish": self.recv_publish,
                    "published": self.sent_published,
                    "event": self.sent_event,
                    "register": self.recv_register,
                    "registered": self.sent_registered,
                    "subscribe": self.recv_subscribe,
                    "subscribed": self.sent_subscribed,
                },
            }
        return obj

    def __str__(self):
        return "\n{}\n".format(pprint.pformat(self.marshal()))

    @property
    def timestamp(self):
        if self._timestamp is None and self._from_fbs:
            self._timestamp = np.datetime64(self._from_fbs.Timestamp(), "ns")
        return self._timestamp

    @timestamp.setter
    def timestamp(self, value):
        assert value is None or isinstance(value, np.datetime64)
        self._timestamp = value

    @property
    def mrealm_id(self):
        if self._mrealm_id is None and self._from_fbs:
            if self._from_fbs.NodeIdLength():
                _mrealm_id = self._from_fbs.MrealmIdAsBytes()
                self._mrealm_id = uuid.UUID(bytes=bytes(_mrealm_id))
        return self._mrealm_id

    @mrealm_id.setter
    def mrealm_id(self, value):
        assert value is None or isinstance(value, uuid.UUID)
        self._mrealm_id = value

    @property
    def node_id(self):
        if self._node_id is None and self._from_fbs:
            if self._from_fbs.NodeIdLength():
                _node_id = self._from_fbs.NodeIdAsBytes()
                self._node_id = uuid.UUID(bytes=bytes(_node_id))
        return self._node_id

    @node_id.setter
    def node_id(self, value):
        assert value is None or isinstance(value, uuid.UUID)
        self._node_id = value

    @property
    def worker_id(self):
        if self._worker_id is None and self._from_fbs:
            _worker_id = self._from_fbs.WorkerId()
            if _worker_id:
                self._worker_id = _worker_id.decode("utf8")
        return self._worker_id

    @worker_id.setter
    def worker_id(self, value):
        assert value is None or type(value) == str
        self._worker_id = value

    @property
    def period(self):
        if self._period is None and self._from_fbs:
            self._period = self._from_fbs.Period()
        return self._period

    @period.setter
    def period(self, value):
        assert value is None or type(value) == int
        self._period = value

    @property
    def type(self):
        if self._type is None and self._from_fbs:
            self._type = self._from_fbs.Type()
        return self._type

    @type.setter
    def type(self, value):
        assert value is None or type(value) == int
        self._type = value

    @property
    def state(self):
        if self._state is None and self._from_fbs:
            self._state = self._from_fbs.State()
        return self._state

    @state.setter
    def state(self, value):
        assert value is None or type(value) == int
        self._state = value

    @property
    def sent(self):
        if self._sent is None and self._from_fbs:
            self._sent = np.datetime64(self._from_fbs.Sent(), "ns")
        return self._sent

    @sent.setter
    def sent(self, value):
        assert value is None or isinstance(value, np.datetime64)
        self._sent = value

    @property
    def seq(self):
        if self._seq is None and self._from_fbs:
            self._seq = self._from_fbs.Seq()
        return self._seq

    @seq.setter
    def seq(self, value):
        assert value is None or type(value) == int
        self._seq = value

    @property
    def num_fds(self):
        if self._num_fds is None and self._from_fbs:
            self._num_fds = self._from_fbs.NumFds()
        return self._num_fds

    @num_fds.setter
    def num_fds(self, value):
        assert value is None or type(value) == int
        self._num_fds = value

    @property
    def num_threads(self):
        if self._num_threads is None and self._from_fbs:
            self._num_threads = self._from_fbs.NumThreads()
        return self._num_threads

    @num_threads.setter
    def num_threads(self, value):
        assert value is None or type(value) == int
        self._num_threads = value

    @property
    def num_ctx_switches_involuntary(self):
        if self._num_ctx_switches_involuntary is None and self._from_fbs:
            self._num_ctx_switches_involuntary = self._from_fbs.NumCtxSwitchesInvoluntary()
        return self._num_ctx_switches_involuntary

    @num_ctx_switches_involuntary.setter
    def num_ctx_switches_involuntary(self, value):
        assert value is None or type(value) == int
        self._num_ctx_switches_involuntary = value

    @property
    def num_ctx_switches_involuntary_per_sec(self):
        if self._num_ctx_switches_involuntary_per_sec is None and self._from_fbs:
            self._num_ctx_switches_involuntary_per_sec = self._from_fbs.NumCtxSwitchesInvoluntaryPerSec()
        return self._num_ctx_switches_involuntary_per_sec

    @num_ctx_switches_involuntary_per_sec.setter
    def num_ctx_switches_involuntary_per_sec(self, value):
        assert value is None or type(value) == int
        self._num_ctx_switches_involuntary_per_sec = value

    @property
    def num_ctx_switches_voluntary(self):
        if self._num_ctx_switches_voluntary is None and self._from_fbs:
            self._num_ctx_switches_voluntary = self._from_fbs.NumCtxSwitchesVoluntary()
        return self._num_ctx_switches_voluntary

    @num_ctx_switches_voluntary.setter
    def num_ctx_switches_voluntary(self, value):
        assert value is None or type(value) == int
        self._num_ctx_switches_voluntary = value

    @property
    def num_ctx_switches_voluntary_per_sec(self):
        if self._num_ctx_switches_voluntary_per_sec is None and self._from_fbs:
            self._num_ctx_switches_voluntary_per_sec = self._from_fbs.NumCtxSwitchesVoluntaryPerSec()
        return self._num_ctx_switches_voluntary_per_sec

    @num_ctx_switches_voluntary_per_sec.setter
    def num_ctx_switches_voluntary_per_sec(self, value):
        assert value is None or type(value) == int
        self._num_ctx_switches_voluntary_per_sec = value

    @property
    def cpu_system(self):
        if self._cpu_system is None and self._from_fbs:
            self._cpu_system = self._from_fbs.CpuSystem()
        return self._cpu_system

    @cpu_system.setter
    def cpu_system(self, value):
        assert value is None or type(value) == float
        self._cpu_system = value

    @property
    def cpu_system_per_sec(self):
        if self._cpu_system_per_sec is None and self._from_fbs:
            self._cpu_system_per_sec = self._from_fbs.CpuSystemPerSec()
        return self._cpu_system_per_sec

    @cpu_system_per_sec.setter
    def cpu_system_per_sec(self, value):
        assert value is None or type(value) == float
        self._cpu_system_per_sec = value

    @property
    def cpu_wait(self):
        if self._cpu_wait is None and self._from_fbs:
            self._cpu_wait = self._from_fbs.CpuWait()
        return self._cpu_wait

    @cpu_wait.setter
    def cpu_wait(self, value):
        assert value is None or type(value) == float
        self._cpu_wait = value

    @property
    def cpu_wait_per_sec(self):
        if self._cpu_wait_per_sec is None and self._from_fbs:
            self._cpu_wait_per_sec = self._from_fbs.CpuWaitPerSec()
        return self._cpu_wait_per_sec

    @cpu_wait_per_sec.setter
    def cpu_wait_per_sec(self, value):
        assert value is None or type(value) == float
        self._cpu_wait_per_sec = value

    @property
    def cpu_user(self):
        if self._cpu_user is None and self._from_fbs:
            self._cpu_user = self._from_fbs.CpuUser()
        return self._cpu_user

    @cpu_user.setter
    def cpu_user(self, value):
        assert value is None or type(value) == float
        self._cpu_user = value

    @property
    def cpu_user_per_sec(self):
        if self._cpu_user_per_sec is None and self._from_fbs:
            self._cpu_user_per_sec = self._from_fbs.CpuUserPerSec()
        return self._cpu_user_per_sec

    @cpu_user_per_sec.setter
    def cpu_user_per_sec(self, value):
        assert value is None or type(value) == float
        self._cpu_user_per_sec = value

    @property
    def read_bytes(self):
        if self._read_bytes is None and self._from_fbs:
            self._read_bytes = self._from_fbs.ReadBytes()
        return self._read_bytes

    @read_bytes.setter
    def read_bytes(self, value):
        assert value is None or type(value) == int
        self._read_bytes = value

    @property
    def read_bytes_per_sec(self):
        if self._read_bytes_per_sec is None and self._from_fbs:
            self._read_bytes_per_sec = self._from_fbs.ReadBytesPerSec()
        return self._read_bytes_per_sec

    @read_bytes_per_sec.setter
    def read_bytes_per_sec(self, value):
        assert value is None or type(value) == int
        self._read_bytes_per_sec = value

    @property
    def read_ios(self):
        if self._read_ios is None and self._from_fbs:
            self._read_ios = self._from_fbs.ReadIos()
        return self._read_ios

    @read_ios.setter
    def read_ios(self, value):
        assert value is None or type(value) == int
        self._read_ios = value

    @property
    def read_ios_per_sec(self):
        if self._read_ios_per_sec is None and self._from_fbs:
            self._read_ios_per_sec = self._from_fbs.ReadIosPerSec()
        return self._read_ios_per_sec

    @read_ios_per_sec.setter
    def read_ios_per_sec(self, value):
        assert value is None or type(value) == int
        self._read_ios_per_sec = value

    @property
    def write_bytes(self):
        if self._write_bytes is None and self._from_fbs:
            self._write_bytes = self._from_fbs.WriteBytes()
        return self._write_bytes

    @write_bytes.setter
    def write_bytes(self, value):
        assert value is None or type(value) == int
        self._write_bytes = value

    @property
    def write_bytes_per_sec(self):
        if self._write_bytes_per_sec is None and self._from_fbs:
            self._write_bytes_per_sec = self._from_fbs.WriteBytesPerSec()
        return self._write_bytes_per_sec

    @write_bytes_per_sec.setter
    def write_bytes_per_sec(self, value):
        assert value is None or type(value) == int
        self._write_bytes_per_sec = value

    @property
    def write_ios(self):
        if self._write_ios is None and self._from_fbs:
            self._write_ios = self._from_fbs.WriteIos()
        return self._write_ios

    @write_ios.setter
    def write_ios(self, value):
        assert value is None or type(value) == int
        self._write_ios = value

    @property
    def write_ios_per_sec(self):
        if self._write_ios_per_sec is None and self._from_fbs:
            self._write_ios_per_sec = self._from_fbs.WriteIosPerSec()
        return self._write_ios_per_sec

    @write_ios_per_sec.setter
    def write_ios_per_sec(self, value):
        assert value is None or type(value) == int
        self._write_ios_per_sec = value

    @property
    def sent_bytes(self):
        if self._sent_bytes is None and self._from_fbs:
            self._sent_bytes = self._from_fbs.SentBytes()
        return self._sent_bytes

    @sent_bytes.setter
    def sent_bytes(self, value):
        assert value is None or type(value) == int
        self._sent_bytes = value

    @property
    def sent_bytes_per_sec(self):
        if self._sent_bytes_per_sec is None and self._from_fbs:
            self._sent_bytes_per_sec = self._from_fbs.SentBytesPerSec()
        return self._sent_bytes_per_sec

    @sent_bytes_per_sec.setter
    def sent_bytes_per_sec(self, value):
        assert value is None or type(value) == int
        self._sent_bytes_per_sec = value

    @property
    def sent_ios(self):
        if self._sent_ios is None and self._from_fbs:
            self._sent_ios = self._from_fbs.SentIos()
        return self._sent_ios

    @sent_ios.setter
    def sent_ios(self, value):
        assert value is None or type(value) == int
        self._sent_ios = value

    @property
    def sent_ios_per_sec(self):
        if self._sent_ios_per_sec is None and self._from_fbs:
            self._sent_ios_per_sec = self._from_fbs.SentIosPerSec()
        return self._sent_ios_per_sec

    @sent_ios_per_sec.setter
    def sent_ios_per_sec(self, value):
        assert value is None or type(value) == int
        self._sent_ios_per_sec = value

    @property
    def recv_bytes(self):
        if self._recv_bytes is None and self._from_fbs:
            self._recv_bytes = self._from_fbs.RecvBytes()
        return self._recv_bytes

    @recv_bytes.setter
    def recv_bytes(self, value):
        assert value is None or type(value) == int
        self._recv_bytes = value

    @property
    def recv_bytes_per_sec(self):
        if self._recv_bytes_per_sec is None and self._from_fbs:
            self._recv_bytes_per_sec = self._from_fbs.RecvBytesPerSec()
        return self._recv_bytes_per_sec

    @recv_bytes_per_sec.setter
    def recv_bytes_per_sec(self, value):
        assert value is None or type(value) == int
        self._recv_bytes_per_sec = value

    @property
    def recv_ios(self):
        if self._recv_ios is None and self._from_fbs:
            self._recv_ios = self._from_fbs.RecvIos()
        return self._recv_ios

    @recv_ios.setter
    def recv_ios(self, value):
        assert value is None or type(value) == int
        self._recv_ios = value

    @property
    def recv_ios_per_sec(self):
        if self._recv_ios_per_sec is None and self._from_fbs:
            self._recv_ios_per_sec = self._from_fbs.RecvIosPerSec()
        return self._recv_ios_per_sec

    @recv_ios_per_sec.setter
    def recv_ios_per_sec(self, value):
        assert value is None or type(value) == int
        self._recv_ios_per_sec = value

    @property
    def router_roles(self):
        if self._router_roles is None and self._from_fbs:
            self._router_roles = self._from_fbs.RouterRoles()
        return self._router_roles

    @router_roles.setter
    def router_roles(self, value):
        assert value is None or type(value) == int
        self._router_roles = value

    @property
    def router_sessions(self):
        if self._router_sessions is None and self._from_fbs:
            self._router_sessions = self._from_fbs.RouterSessions()
        return self._router_sessions

    @router_sessions.setter
    def router_sessions(self, value):
        assert value is None or type(value) == int
        self._router_sessions = value

    @property
    def recv_call(self):
        if self._recv_call is None and self._from_fbs:
            self._recv_call = self._from_fbs.RecvCall()
        return self._recv_call

    @recv_call.setter
    def recv_call(self, value):
        assert value is None or type(value) == int
        self._recv_call = value

    @property
    def recv_yield(self):
        if self._recv_yield is None and self._from_fbs:
            self._recv_yield = self._from_fbs.RecvYield()
        return self._recv_yield

    @recv_yield.setter
    def recv_yield(self, value):
        assert value is None or type(value) == int
        self._recv_yield = value

    @property
    def sent_invocation(self):
        if self._sent_invocation is None and self._from_fbs:
            self._sent_invocation = self._from_fbs.SentInvocation()
        return self._sent_invocation

    @sent_invocation.setter
    def sent_invocation(self, value):
        assert value is None or type(value) == int
        self._sent_invocation = value

    @property
    def sent_result(self):
        if self._sent_result is None and self._from_fbs:
            self._sent_result = self._from_fbs.SentResult()
        return self._sent_result

    @sent_result.setter
    def sent_result(self, value):
        assert value is None or type(value) == int
        self._sent_result = value

    @property
    def recv_publish(self):
        if self._recv_publish is None and self._from_fbs:
            self._recv_publish = self._from_fbs.RecvPublish()
        return self._recv_publish

    @recv_publish.setter
    def recv_publish(self, value):
        assert value is None or type(value) == int
        self._recv_publish = value

    @property
    def sent_published(self):
        if self._sent_published is None and self._from_fbs:
            self._sent_published = self._from_fbs.SentPublished()
        return self._sent_published

    @sent_published.setter
    def sent_published(self, value):
        assert value is None or type(value) == int
        self._sent_published = value

    @property
    def sent_event(self):
        if self._sent_event is None and self._from_fbs:
            self._sent_event = self._from_fbs.SentEvent()
        return self._sent_event

    @sent_event.setter
    def sent_event(self, value):
        assert value is None or type(value) == int
        self._sent_event = value

    @property
    def recv_register(self):
        if self._recv_register is None and self._from_fbs:
            self._recv_register = self._from_fbs.RecvRegister()
        return self._recv_register

    @recv_register.setter
    def recv_register(self, value):
        assert value is None or type(value) == int
        self._recv_register = value

    @property
    def sent_registered(self):
        if self._sent_registered is None and self._from_fbs:
            self._sent_registered = self._from_fbs.SentRegistered()
        return self._sent_registered

    @sent_registered.setter
    def sent_registered(self, value):
        assert value is None or type(value) == int
        self._sent_registered = value

    @property
    def recv_subscribe(self):
        if self._recv_subscribe is None and self._from_fbs:
            self._recv_subscribe = self._from_fbs.RecvSubscribe()
        return self._recv_subscribe

    @recv_subscribe.setter
    def recv_subscribe(self, value):
        assert value is None or type(value) == int
        self._recv_subscribe = value

    @property
    def sent_subscribed(self):
        if self._sent_subscribed is None and self._from_fbs:
            self._sent_subscribed = self._from_fbs.SentSubscribed()
        return self._sent_subscribed

    @sent_subscribed.setter
    def sent_subscribed(self, value):
        assert value is None or type(value) == int
        self._sent_subscribed = value

    @staticmethod
    def cast(buf):
        return MWorkerLog(_MWorkerLogGen.GetRootAsMWorkerLog(buf, 0))

    def build(self, builder):
        mrealm_id = self.mrealm_id.bytes if self.mrealm_id else None
        if mrealm_id:
            mrealm_id = builder.CreateString(mrealm_id)

        node_id = self.node_id.bytes if self.node_id else None
        if node_id:
            node_id = builder.CreateString(node_id)

        worker_id = None
        if self.worker_id:
            worker_id = builder.CreateString(self.worker_id)

        MWorkerLogGen.MWorkerLogStart(builder)

        if self.timestamp:
            MWorkerLogGen.MWorkerLogAddTimestamp(builder, int(self.timestamp))

        if mrealm_id:
            MWorkerLogGen.MWorkerLogAddMrealmId(builder, mrealm_id)

        if node_id:
            MWorkerLogGen.MWorkerLogAddNodeId(builder, node_id)

        if worker_id:
            MWorkerLogGen.MWorkerLogAddWorkerId(builder, worker_id)

        if self.period:
            MWorkerLogGen.MWorkerLogAddPeriod(builder, self.period)

        if self.type:
            MWorkerLogGen.MWorkerLogAddType(builder, self.type)

        if self.state:
            MWorkerLogGen.MWorkerLogAddState(builder, self.state)

        if self.sent:
            MWorkerLogGen.MWorkerLogAddSent(builder, int(self.sent))

        if self.seq:
            MWorkerLogGen.MWorkerLogAddSeq(builder, self.seq)

        if self.num_fds:
            MWorkerLogGen.MWorkerLogAddNumFds(builder, self.num_fds)

        if self.num_threads:
            MWorkerLogGen.MWorkerLogAddNumThreads(builder, self.num_threads)

        if self.num_ctx_switches_involuntary:
            MWorkerLogGen.MWorkerLogAddNumCtxSwitchesInvoluntary(builder, self.num_ctx_switches_involuntary)

        if self.num_ctx_switches_involuntary_per_sec:
            MWorkerLogGen.MWorkerLogAddNumCtxSwitchesInvoluntaryPerSec(
                builder, self.num_ctx_switches_involuntary_per_sec
            )

        if self.num_ctx_switches_voluntary:
            MWorkerLogGen.MWorkerLogAddNumCtxSwitchesVoluntary(builder, self.num_ctx_switches_voluntary)

        if self.num_ctx_switches_voluntary_per_sec:
            MWorkerLogGen.MWorkerLogAddNumCtxSwitchesVoluntaryPerSec(builder, self.num_ctx_switches_voluntary_per_sec)

        if self.cpu_system:
            MWorkerLogGen.MWorkerLogAddCpuSystem(builder, self.cpu_system)

        if self.cpu_system_per_sec:
            MWorkerLogGen.MWorkerLogAddCpuSystemPerSec(builder, self.cpu_system_per_sec)

        if self.cpu_wait:
            MWorkerLogGen.MWorkerLogAddCpuWait(builder, self.cpu_wait)

        if self.cpu_wait_per_sec:
            MWorkerLogGen.MWorkerLogAddCpuWaitPerSec(builder, self.cpu_wait_per_sec)

        if self.cpu_user:
            MWorkerLogGen.MWorkerLogAddCpuUser(builder, self.cpu_user)

        if self.cpu_user_per_sec:
            MWorkerLogGen.MWorkerLogAddCpuUserPerSec(builder, self.cpu_user_per_sec)

        if self.read_bytes:
            MWorkerLogGen.MWorkerLogAddReadBytes(builder, self.read_bytes)

        if self.read_bytes_per_sec:
            MWorkerLogGen.MWorkerLogAddReadBytesPerSec(builder, self.read_bytes_per_sec)

        if self.read_ios:
            MWorkerLogGen.MWorkerLogAddReadIos(builder, self.read_ios)

        if self.read_ios_per_sec:
            MWorkerLogGen.MWorkerLogAddReadIosPerSec(builder, self.read_ios_per_sec)

        if self.write_bytes:
            MWorkerLogGen.MWorkerLogAddWriteBytes(builder, self.write_bytes)

        if self.write_bytes_per_sec:
            MWorkerLogGen.MWorkerLogAddWriteBytesPerSec(builder, self.write_bytes_per_sec)

        if self.write_ios:
            MWorkerLogGen.MWorkerLogAddWriteIos(builder, self.write_ios)

        if self.write_ios_per_sec:
            MWorkerLogGen.MWorkerLogAddWriteIosPerSec(builder, self.write_ios_per_sec)

        if self.sent_bytes:
            MWorkerLogGen.MWorkerLogAddSentBytes(builder, self.sent_bytes)

        if self.sent_bytes_per_sec:
            MWorkerLogGen.MWorkerLogAddSentBytesPerSec(builder, self.sent_bytes_per_sec)

        if self.sent_ios:
            MWorkerLogGen.MWorkerLogAddSentIos(builder, self.sent_ios)

        if self.sent_ios_per_sec:
            MWorkerLogGen.MWorkerLogAddSentIosPerSec(builder, self.sent_ios_per_sec)

        if self.recv_bytes:
            MWorkerLogGen.MWorkerLogAddRecvBytes(builder, self.recv_bytes)

        if self.recv_bytes_per_sec:
            MWorkerLogGen.MWorkerLogAddRecvBytesPerSec(builder, self.recv_bytes_per_sec)

        if self.recv_ios:
            MWorkerLogGen.MWorkerLogAddRecvIos(builder, self.recv_ios)

        if self.recv_ios_per_sec:
            MWorkerLogGen.MWorkerLogAddRecvIosPerSec(builder, self.recv_ios_per_sec)

        if self.router_roles:
            MWorkerLogGen.MWorkerLogAddRouterRoles(builder, self.router_roles)

        if self.router_sessions:
            MWorkerLogGen.MWorkerLogAddRouterSessions(builder, self.router_sessions)

        if self.recv_call:
            MWorkerLogGen.MWorkerLogAddRecvCall(builder, self.recv_call)

        if self.recv_yield:
            MWorkerLogGen.MWorkerLogAddRecvYield(builder, self.recv_yield)

        if self.sent_invocation:
            MWorkerLogGen.MWorkerLogAddSentInvocation(builder, self.sent_invocation)

        if self.sent_result:
            MWorkerLogGen.MWorkerLogAddSentResult(builder, self.sent_result)

        if self.recv_publish:
            MWorkerLogGen.MWorkerLogAddRecvPublish(builder, self.recv_publish)

        if self.sent_published:
            MWorkerLogGen.MWorkerLogAddSentPublished(builder, self.sent_published)

        if self.sent_event:
            MWorkerLogGen.MWorkerLogAddSentEvent(builder, self.sent_event)

        if self.recv_register:
            MWorkerLogGen.MWorkerLogAddRecvRegister(builder, self.recv_register)

        if self.sent_registered:
            MWorkerLogGen.MWorkerLogAddSentRegistered(builder, self.sent_registered)

        if self.recv_subscribe:
            MWorkerLogGen.MWorkerLogAddRecvSubscribe(builder, self.recv_subscribe)

        if self.sent_subscribed:
            MWorkerLogGen.MWorkerLogAddSentSubscribed(builder, self.sent_subscribed)

        final = MWorkerLogGen.MWorkerLogEnd(builder)

        return final
