# Copyright (C) 2023-2024 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
from enum import Enum

import gdb
from gdb.missing_debug import MissingDebugHandler

# A global log that is filled in by instances of the LOG_HANDLER class
# when they are called.
handler_call_log = []


class Mode(Enum):
    RETURN_NONE = 0
    RETURN_TRUE = 1
    RETURN_FALSE = 2
    RETURN_STRING = 3


class handler(MissingDebugHandler):
    def __init__(self):
        super().__init__("handler")
        self._call_count = 0
        self._mode = Mode.RETURN_NONE

    def __call__(self, objfile):
        global handler_call_log
        handler_call_log.append(self.name)
        self._call_count += 1
        if self._mode == Mode.RETURN_NONE:
            return None

        if self._mode == Mode.RETURN_TRUE:
            os.rename(self._src, self._dest)
            return True

        if self._mode == Mode.RETURN_FALSE:
            return False

        if self._mode == Mode.RETURN_STRING:
            return self._dest

        assert False

    @property
    def call_count(self):
        """Return a count, the number of calls to __call__ since the last
        call to set_mode.
        """
        return self._call_count

    def set_mode(self, mode, *args):
        self._call_count = 0
        self._mode = mode

        if mode == Mode.RETURN_NONE:
            assert len(args) == 0
            return

        if mode == Mode.RETURN_TRUE:
            assert len(args) == 2
            self._src = args[0]
            self._dest = args[1]
            return

        if mode == Mode.RETURN_FALSE:
            assert len(args) == 0
            return

        if mode == Mode.RETURN_STRING:
            assert len(args) == 1
            self._dest = args[0]
            return

        assert False


class exception_handler(MissingDebugHandler):
    def __init__(self):
        super().__init__("exception_handler")
        self.exception_type = None

    def __call__(self, objfile):
        global handler_call_log
        handler_call_log.append(self.name)
        assert self.exception_type is not None
        raise self.exception_type("message")


class log_handler(MissingDebugHandler):
    def __call__(self, objfile):
        global handler_call_log
        handler_call_log.append(self.name)
        return None


# A basic helper function, this keeps lines shorter in the TCL script.
def register(name, locus=None):
    gdb.missing_debug.register_handler(locus, log_handler(name))


# Create instances of the handlers, but don't install any.  We install
# these as needed from the TCL script.
rhandler = exception_handler()
handler_obj = handler()

print("Success")
