# Autogenerated file. Do not edit.
from jacdac.bus import Bus, Client, EventHandlerFn, UnsubscribeFn
from .constants import *
from typing import Optional


class JacscriptManagerClient(Client):
    """
    Allows for deployment and control over Jacscript virtual machine.
     * 
     * Programs start automatically after device restart or uploading of new program.
     * You can stop programs until next reset by setting the `running` register to `0`.
     * 
     * TODO - debug interface:
     * * read-globals command/register
     * * globals-changed pipe
     * * breakpoint command
     * * some performance monitoring?
    Implements a client for the `Jacscript Manager <https://microsoft.github.io/jacdac-docs/services/jacscriptmanager>`_ service.

    """

    def __init__(self, bus: Bus, role: str) -> None:
        super().__init__(bus, JD_SERVICE_CLASS_JACSCRIPT_MANAGER, JD_JACSCRIPT_MANAGER_PACK_FORMATS, role)


    @property
    def running(self) -> Optional[bool]:
        """
        Indicates if the program is currently running.
        To restart the program, stop it (write `0`), read back the register to make sure it's stopped,
        start it, and read back., 
        """
        return self.register(JD_JACSCRIPT_MANAGER_REG_RUNNING).bool_value()

    @running.setter
    def running(self, value: bool) -> None:
        self.register(JD_JACSCRIPT_MANAGER_REG_RUNNING).set_values(value)


    @property
    def autostart(self) -> Optional[bool]:
        """
        Indicates wheather the program should be re-started upon `reboot()` or `panic()`.
        Defaults to `true`., 
        """
        return self.register(JD_JACSCRIPT_MANAGER_REG_AUTOSTART).bool_value()

    @autostart.setter
    def autostart(self, value: bool) -> None:
        self.register(JD_JACSCRIPT_MANAGER_REG_AUTOSTART).set_values(value)


    @property
    def logging(self) -> Optional[bool]:
        """
        `log_message` reports are only sent when this is `true`.
        It defaults to `false`., 
        """
        return self.register(JD_JACSCRIPT_MANAGER_REG_LOGGING).bool_value()

    @logging.setter
    def logging(self, value: bool) -> None:
        self.register(JD_JACSCRIPT_MANAGER_REG_LOGGING).set_values(value)


    @property
    def program_size(self) -> Optional[int]:
        """
        The size of current program., 
        """
        return self.register(JD_JACSCRIPT_MANAGER_REG_PROGRAM_SIZE).value()

    @property
    def program_hash(self) -> Optional[int]:
        """
        Return FNV1A hash of the current bytecode., 
        """
        return self.register(JD_JACSCRIPT_MANAGER_REG_PROGRAM_HASH).value()

    def on_program_panic(self, handler: EventHandlerFn) -> UnsubscribeFn:
        """
        Emitted when the program calls `panic(panic_code)` or `reboot()` (`panic_code == 0` in that case).
        The byte offset in byte code of the call is given in `program_counter`.
        The program will restart immediately when `panic_code == 0` or in a few seconds otherwise.
        """
        return self.on_event(JD_JACSCRIPT_MANAGER_EV_PROGRAM_PANIC, handler)

    def on_program_change(self, handler: EventHandlerFn) -> UnsubscribeFn:
        """
        Emitted after bytecode of the program has changed.
        """
        return self.on_event(JD_JACSCRIPT_MANAGER_EV_PROGRAM_CHANGE, handler)


    def deploy_bytecode(self, bytecode_size: int) -> None:
        """
        Open pipe for streaming in the bytecode of the program. The size of the bytecode has to be declared upfront.
        To clear the program, use `bytecode_size == 0`.
        The bytecode is streamed over regular pipe data packets.
        The bytecode shall be fully written into flash upon closing the pipe.
        If `autostart` is true, the program will start after being deployed.
        The data payloads, including the last one, should have a size that is a multiple of 32 bytes.
        Thus, the initial bytecode_size also needs to be a multiple of 32.
        """
        self.send_cmd_packed(JD_JACSCRIPT_MANAGER_CMD_DEPLOY_BYTECODE, bytecode_size)
    
