# Enthought library imports.
from pyface.tasks.api import (
    Task,
    TaskLayout,
    PaneItem,
    IEditor,
    IEditorAreaPane,
    SplitEditorAreaPane,
)
from pyface.tasks.action.api import (
    DockPaneToggleGroup,
    SMenuBar,
    SMenu,
    SToolBar,
    TaskAction,
)
from pyface.api import (
    ConfirmationDialog,
    FileDialog,
    ImageResource,
    YES,
    OK,
    CANCEL,
)
from traits.api import on_trait_change, Property, Instance

# Local imports.
from example_panes import PythonScriptBrowserPane
from python_editor import PythonEditor


class ExampleTask(Task):
    """ A simple task for editing Python code.
    """

    #### Task interface #######################################################

    id = "example.example_task"
    name = "Multi-Tab Editor"

    active_editor = Property(
        Instance(IEditor), observe="editor_area.active_editor"
    )

    editor_area = Instance(IEditorAreaPane)

    menu_bar = SMenuBar(
        SMenu(
            TaskAction(name="New", method="new", accelerator="Ctrl+N"),
            TaskAction(name="Open...", method="open", accelerator="Ctrl+O"),
            TaskAction(name="Save", method="save", accelerator="Ctrl+S"),
            id="File",
            name="&File",
        ),
        SMenu(DockPaneToggleGroup(), id="View", name="&View"),
    )

    tool_bars = [
        SToolBar(
            TaskAction(
                method="new",
                tooltip="New file",
                image=ImageResource("document_new"),
            ),
            TaskAction(
                method="open",
                tooltip="Open a file",
                image=ImageResource("document_open"),
            ),
            TaskAction(
                method="save",
                tooltip="Save the current file",
                image=ImageResource("document_save"),
            ),
            image_size=(32, 32),
        )
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def _default_layout_default(self):
        return TaskLayout(left=PaneItem("example.python_script_browser_pane"))

    def activated(self):
        """ Overriden to set the window's title.
        """
        return
        filename = self.active_editor.path if self.active_editor else ""
        self.window.title = filename if filename else "Untitled"

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        self.editor_area = SplitEditorAreaPane()
        return self.editor_area

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        browser = PythonScriptBrowserPane()
        handler = lambda: self._open_file(browser.selected_file)
        browser.on_trait_change(handler, "activated")
        return [browser]

    ###########################################################################
    # 'ExampleTask' interface.
    ###########################################################################

    def new(self):
        """ Opens a new empty window
        """
        editor = PythonEditor()
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    def open(self):
        """ Shows a dialog to open a file.
        """
        dialog = FileDialog(parent=self.window.control, wildcard="*.py")
        if dialog.open() == OK:
            self._open_file(dialog.path)

    def save(self):
        """ Attempts to save the current file, prompting for a path if
            necessary. Returns whether the file was saved.
        """
        editor = self.active_editor
        try:
            editor.save()
        except IOError:
            # If you are trying to save to a file that doesn't exist, open up a
            # FileDialog with a 'save as' action.
            dialog = FileDialog(
                parent=self.window.control, action="save as", wildcard="*.py"
            )
            if dialog.open() == OK:
                editor.save(dialog.path)
            else:
                return False
        return True

    ###########################################################################
    # Protected interface.
    ###########################################################################

    def _open_file(self, filename):
        """ Opens the file at the specified path in the editor.
        """
        editor = PythonEditor(path=filename)
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    def _prompt_for_save(self):
        """ Prompts the user to save if necessary. Returns whether the dialog
            was cancelled.
        """
        dirty_editors = dict(
            [
                (editor.name, editor)
                for editor in self.editor_area.editors
                if editor.dirty
            ]
        )
        if not dirty_editors.keys():
            return True
        message = "You have unsaved files. Would you like to save them?"
        dialog = ConfirmationDialog(
            parent=self.window.control,
            message=message,
            cancel=True,
            default=CANCEL,
            title="Save Changes?",
        )
        result = dialog.open()
        if result == CANCEL:
            return False
        elif result == YES:
            for name, editor in dirty_editors.items():
                editor.save(editor.path)
        return True

    #### Trait change handlers ################################################

    @on_trait_change("window:closing")
    def _prompt_on_close(self, event):
        """ Prompt the user to save when exiting.
        """
        close = self._prompt_for_save()
        event.veto = not close

    #### Trait property getter/setters ########################################

    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None
