# Enthought library imports.
from pyface.tasks.api import Task, TaskLayout, PaneItem
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

# Local imports.
from example_panes import PythonEditorPane, PythonScriptBrowserPane


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

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

    id = 'example.example_task'
    name = 'Python Script Editor'

    #default_layout = TaskLayout(
    #    left=PaneItem('example.python_script_browser_pane'))

    menu_bar = SMenuBar(SMenu(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='open',
                                      tooltip='Open a file',
                                      image=ImageResource('document_open')),
                           TaskAction(method='save',
                                      tooltip='Save the current file',
                                      image=ImageResource('document_save'))) ]

    ###########################################################################
    # '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.
        """
        filename = self.window.central_pane.editor.path
        self.window.title = filename if filename else 'Untitled'

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        return PythonEditorPane()

    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 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.window.central_pane.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.
        """
        if self._prompt_for_save():
            self.window.central_pane.editor.path = filename
            self.activated()

    def _prompt_for_save(self):
        """ Prompts the user to save if necessary. Returns whether the dialog
            was cancelled.
        """
        if self.window.central_pane.editor.dirty:
            message = 'The current file has unsaved changes. ' \
                      'Do you want to save your changes?'
            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:
                if not self.save():
                    return self._prompt_for_save()
        return True

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