from __future__ import annotations

from .AFXGuiCommand import AFXGuiCommand
from .AFXGuiObjectManager import AFXGuiObjectManager
from .AFXMode import AFXMode
from .FXObject import FXObject


class AFXGuiMode(AFXMode):
    """This class is the abstract base class for modes."""

    #: Used to destroy dialogs.
    ID_DESTROY_DIALOGS: int = hash("ID_DESTROY_DIALOGS")

    #: Used to handle bailout.
    ID_HANDLE_BAILOUT: int = hash("ID_HANDLE_BAILOUT")

    def __init__(self, owner: AFXGuiObjectManager):
        """Constructor.

        Parameters
        ----------
        owner : AFXGuiObjectManager
            Owner (a module or a toolset) of the mode.
        """

    def activate(self):
        """Performs the necessary tasks when the mode is activated.

        Reimplemented in AFXForm, and AFXProcedure.
        """

    def cancel(self, tgt: FXObject | None = None, msg: int = 0):
        """Requests a cancellation of the mode. When the cancel operation completes, successfully or not, the
        target will be sent the given message. The message data pointer will be non-zero for successful
        cancellation and zero if the cancel operation was abandoned for some purpose.

        Parameters
        ----------
        tgt : FXObject | None
            Completion message target.
        msg : int
            Completion message ID.
        """

    def commit(self):
        """Performs the necessary tasks when a dialog box of the mode commits.

        Implemented in AFXForm, and AFXProcedure.
        """

    def continueMode(self):
        """Virtual method that must be defined in the derived class--used to get the next dialog box or step in
        the mode.

        Implemented in AFXForm, and AFXProcedure.
        """

    def deactivate(self):
        """Performs the necessary tasks when the mode is deactivated.

        Reimplemented in AFXProcedureForm, and AFXProcedure.
        """

    def destroyDialogs(self):
        """Destroys the associated dialogs when the mode is deactivated.

        The exact behavior of this function is controlled by the return value of dialog box's
        getDeactivateAction() method.
        """

    def doCustomChecks(self):
        """This class provides an empty implementation of this method; the derived class should redefine this
        method to perform its specific verifications on the user input."""

    def doCustomTasks(self):
        """This class provides an empty implementation of this method, which is called after the commands are
        processed successfully.

        The derived class should redefine this method to perform its specific tasks such as writing a
        confirmation message to the main window.
        """

    def getCommandString(self):
        """Returns a string containing a list of commands generated by each command associated with the mode."""

    def getCurrentDialog(self):
        """Returns the dialog box currently posted by the mode (may be NULL)."""

    def getModeName(self):
        """Returns the mode's name."""

    def getOwner(self):
        """Returns the mode's owner (a module or a tool set)."""

    def getPressedButtonId(self):
        """Returns the ID of the button that the user pressed in the currently posted dialog box."""

    def handleException(self, exc):
        """Posts a dialog box with an error message for the given exception. The derived class should redefine
        this method if it needs to handle the exception differently.

        Parameters
        ----------
        exc : nex_Exception
            Exception.
        """

    def handleKeywordException(self, exc):
        """Posts a dialog box with an error message for the given exception thrown by a keyword during data
        validation.

        Parameters
        ----------
        exc : nex_Exception
            Exception.
        """

    def isKeyword(self, object: FXObject):
        """Returns True if the object is one of the mode's keywords.

        Parameters
        ----------
        object : FXObject
        """

    def issueCommands(self, writeToReplay: bool = True, writeToJournal: bool = False):
        """Generates commands based on the current state, sends the commands, and deactivates the mode if
        necessary. If the commands did not complete successfully, a dialog box will be posted with an error
        message.

        Parameters
        ----------
        writeToReplay : bool
            True if commands should be written to the replay file; False if not.
        writeToJournal : bool
            True if commands should be written to the journal file; False if not.
        """

    def okToCancel(self):
        """Method indicating if the dialog box should be cancelled if the context changes (for example, if the
        user opens a new database); the base class implementation returns True indicating it is OK to cancel the
        mode, derived classes can overwrite this method and return False to prevent the mode from being canceled
        during a context change."""

    def onKeywordsUpdated(self, command: AFXGuiCommand):
        """Hook method called whenever the command's object changes in Kernel. By default this function does
        nothing.

        Parameters
        ----------
        command : AFXGuiCommand
            Command for which the query fired.
        """

    def registerDefaultsObject(self, command: AFXGuiCommand, objectName: str):
        """Registers the defaults object that will be queried when the Defaults button in the dialog box is
        pressed.

        Parameters
        ----------
        command : AFXGuiCommand
            Command whose keywords to be populated with the defaults object values.
        objectName : str
            Name of defaults object to be queried.
        """

    def registerQueries(self):
        """Registers queries with the GUI infrastructure for the mode's active commands and unregisters queries
        for the inactive ones."""

    def removeAllProxies(self):
        """Unregisters queries and deletes all the associated proxies."""

    def sendCommandString(self, command: str, writeToReplay: bool = True, writeToJournal: bool = False):
        """Sends the given command string (which can contain multiple commands, separated by command
        delimiters).

        Parameters
        ----------
        command : str
            Command string.
        writeToReplay : bool
            True if commands should be written to the replay file; False if not.
        writeToJournal : bool
            True if commands should be written to the journal file; False if not.
        """

    def setModeName(self, name: str):
        """Sets the mode's name.

        Parameters
        ----------
        name : str
        """

    def unregisterAllQueries(self):
        """Unregisters queries with the GUI infrastructure for all the mode's commands."""

    def verify(self):
        """Verifies each active command associated with the mode and throws an exception if any command contains
        keywords with invalid data."""

    def verifyCurrentKeywordValues(self):
        """Checks whether keywords of active commands for the current dialog box contain valid data and, if not,
        posts a dialog box with an error message.

        Reimplemented in AFXProcedure.
        """

    def verifyKeywordValues(self):
        """Checks whether keywords of active commands contain valid data and, if not, posts a dialog box with an
        error message."""
