from .node_controller import NodePlainController
import atexit
import logging
import signal

logger = logging.getLogger(__name__)


class BitcoindPlainController(NodePlainController):
    """A Controller specifically for the Bitcoind-process"""

    def __init__(
        self,
        bitcoind_path="bitcoind",
        rpcport=18443,
        network="regtest",
        rpcuser="bitcoin",
        rpcpassword="secret",
    ):
        # Just call super and add the node_impl
        super().__init__(
            "bitcoin",
            node_path=bitcoind_path,
            rpcport=rpcport,
            network=network,
            rpcuser=rpcuser,
            rpcpassword=rpcpassword,
        )

    def start_bitcoind(
        self,
        cleanup_at_exit=False,
        cleanup_hard=False,
        datadir=None,
        log_stdout=False,
        extra_args=[],
        timeout=60,
    ):
        """starts bitcoind with a specific rpcport=18543 by default.
        That's not the standard in order to make pytest running while
        developing locally against a different regtest-instance
        if bitcoind_path == docker, it'll run bitcoind via docker.
        Specify a longer timeout for slower devices (e.g. Raspberry Pi)
        """
        # convenience method
        return self.start_node(
            cleanup_at_exit,
            cleanup_hard,
            datadir,
            log_stdout,
            extra_args,
            timeout,
        )

    def attach_to_proc_id(self, bitcoind_process):
        """This assumes that the calling context (prob. a internal_node instance) found a process which is suited.
        So instead of starting, we're somehow faking a start.
        This behaviour should be explicitely triggered as the management of that should be duty of InternalNode
        """
        # avoid circular reference
        from ..internal_node import BitcoindProcess

        self.datadir = bitcoind_process.get_cmd_arg_value("datadir")
        self.node_proc = bitcoind_process
        self.cleanup_hard = (
            False  # assuming an internal node which should not get killed -9
        )

        def cleanup_node_callback(signal_number=None, stack=None):
            self.cleanup_node(False, self.datadir)

        atexit.register(cleanup_node_callback)
        # This is for CTRL-C --> SIGINT
        signal.signal(signal.SIGINT, cleanup_node_callback)
        # This is for kill $pid --> SIGTERM
        signal.signal(signal.SIGTERM, cleanup_node_callback)

        self.status = "Running"

    def stop_bitcoind(self):
        return self.stop_node()

    def version(self):
        """Returns the version of bitcoind, e.g. "v0.19.1" """
        version = self.get_rpc().getnetworkinfo()["subversion"]
        version = version.replace("/", "").replace("Satoshi:", "v")
        return version
