"""Subclass of PyMethodPane, which is generated by wxFormBuilder."""

import wx.aui
import wx.stc
from ctx import theContext as context
import tran
from app.ui import pane
from app.handlers import IdentifiersHandler as ID
from activity.models.handlers.py import EditorHandler
from activity.models.ui import ui as ui


# Implementing PyMethodPane
class PyMethodPane(ui.PyMethodPane):
    """Implements method pane editor"""

    #command ids: run
    _closePane  = ID.register('close-pane')
    _saveCode = ID.new()
    _undoCode = ID.register('undo')
    _redoCode = ID.register('redo')
    _copyCode = ID.register('copy')
    _cutCode = ID.register('cut')
    _pasteCode = ID.register('paste')
    _deleteCode = ID.register('delete')
    _toggleFull = ID.register('fullscreen')
    _navigator = ID.new()

    def _create_toolbars(self):
        """Create custom toolbar"""
        self.m_localToolbar = wx.aui.AuiToolBar(self, wx.ID_ANY, wx.DefaultPosition,
            wx.DefaultSize, wx.aui.AUI_TB_HORZ_LAYOUT)
        self.m_save = self.m_localToolbar.AddTool(self._saveCode,
            u"save code", wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR),
            wx.NullBitmap, wx.ITEM_NORMAL, u"Save", wx.EmptyString, None)
        self.m_localToolbar.AddSeparator()
        self.m_undo = self.m_localToolbar.AddTool(self._undoCode, u"tool",
            wx.ArtProvider.GetBitmap(wx.ART_UNDO, wx.ART_TOOLBAR), wx.NullBitmap, wx.ITEM_NORMAL,
            u"Undo", wx.EmptyString, None)
        self.m_redo = self.m_localToolbar.AddTool(self._redoCode, u"tool",
            wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_TOOLBAR), wx.NullBitmap, wx.ITEM_NORMAL,
            u"Redo", wx.EmptyString, None)
        self.m_localToolbar.AddSeparator()
        self.m_copy = self.m_localToolbar.AddTool(self._copyCode, u"copy",
            wx.ArtProvider.GetBitmap(wx.ART_COPY, wx.ART_TOOLBAR), wx.NullBitmap, wx.ITEM_NORMAL,
            u"Copy", wx.EmptyString, None)
        self.m_cut = self.m_localToolbar.AddTool(self._cutCode, u"cut", wx.ArtProvider.GetBitmap(
            wx.ART_CUT, wx.ART_TOOLBAR), wx.NullBitmap, wx.ITEM_NORMAL, u"Cut", wx.EmptyString, None)
        self.m_paste = self.m_localToolbar.AddTool(self._pasteCode, u"paste",
            wx.ArtProvider.GetBitmap(wx.ART_PASTE, wx.ART_TOOLBAR), wx.NullBitmap,
            wx.ITEM_NORMAL, u"Paste", wx.EmptyString, None)
        self.m_localToolbar.AddSeparator()
        self.m_delete = self.m_localToolbar.AddTool(self._deleteCode, u"delete",
            wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_TOOLBAR), wx.NullBitmap, wx.ITEM_NORMAL,
            u"Delete", wx.EmptyString, None)
        self.m_localToolbar.AddSeparator()
        self.m_fullScreen = self.m_localToolbar.AddTool(self._toggleFull, u"tool",
            wx.ArtProvider.GetBitmap(u"gtk-fullscreen", wx.ART_TOOLBAR), wx.NullBitmap, wx.ITEM_NORMAL,
            u"Toggle fullscreen", wx.EmptyString, None)
        self.m_localToolbar.AddSeparator()
        self.m_navigator = self.m_localToolbar.AddTool(self._navigator, u"tool", wx.Bitmap(u"app/res/method.xpm",
            wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, u"insert call", wx.EmptyString, None)
        self.m_localToolbar.Realize()
        self.m_toolbarSizer.Add(self.m_localToolbar, 0, wx.ALL, 5)
        self.Layout()
        # Connect Events
        self.m_editor.Bind(wx.EVT_KILL_FOCUS, self.OnLeaveFocus)
        self.m_editor.Bind(wx.EVT_SET_FOCUS, self.OnGetFocus)

    def __init__(self, parent, mainframe, method):
        """Intialization of method editor"""
        self._editorArgs = {
            'language': 'python',
            'handler': EditorHandler(text=method._content,
                use_bookmarks=False,
                use_breakpoints=False,
                read_only=method._readOnly)
        }
        super(PyMethodPane, self).__init__(parent)
        self._mainframe = mainframe
        self._object = method
        self._types = {}
        self._notebook = parent

        """
        if method.note:
            self.m_editor.AnnotationSetVisible(wx.stc.STC_ANNOTATION_BOXED)
            self.m_editor.AnnotationSetText(0, method._note)"""
        #self.m_editor.SendMsg(2540, wp="Prueba de anotacion", lp=long(0))
        #self.m_editor.SendMsg(2548, wp=1, lp=long(0))
        self.Layout()
        self._create_toolbars()
        wx.stc.EVT_STC_CHANGE(self.m_editor,
            self.m_editor.GetId(), self.OnEditorChange)

        #self.Bind(EVT_STC_STYLENEEDED, self.handleStyleNeeded,
        #id=self.m_editor.GetId())
        frame = context.frame

        self.Bind(wx.EVT_MENU, frame.CloseCurrentDocPane, id=self._closePane)
        self.Bind(wx.EVT_MENU, self.OnDeleteCode, id=self._deleteCode)
        self.Bind(wx.EVT_MENU, self.OnUndoCode, id=self._undoCode)
        self.Bind(wx.EVT_MENU, self.OnRedoCode, id=self._redoCode)
        self.Bind(wx.EVT_MENU, self.OnCopyCode, id=self._copyCode)
        self.Bind(wx.EVT_MENU, self.OnPasteCode, id=self._pasteCode)
        self.Bind(wx.EVT_MENU, self.OnCutCode, id=self._cutCode)
        self.Bind(wx.EVT_MENU, self.OnSaveCode, id=self._saveCode)
        self.Bind(wx.EVT_MENU, self.OnFullScreen, id=self._toggleFull)

        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateDeleteCode, id=self._deleteCode)
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUndoCode, id=self._undoCode)
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateRedoCode, id=self._redoCode)
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateCopyCode, id=self._copyCode)
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdatePasteCode, id=self._pasteCode)
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateCutCode, id=self._cutCode)
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateSaveCode, id=self._saveCode)

        self.m_editor.popup_handler = self
        self._fullScreen = None

        aTable = wx.AcceleratorTable([
            wx.AcceleratorEntry(wx.ACCEL_ALT | wx.ACCEL_CTRL, ord('F'), self._toggleFull),
            wx.AcceleratorEntry(wx.ACCEL_CTRL, ord('W'), self._closePane),
            wx.AcceleratorEntry(wx.ACCEL_CTRL, ord('S'), self._saveCode),
            wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_DELETE, self._deleteCode)
        ])
        self.SetAcceleratorTable(aTable)

    def Refresh(self):
        """Update editor from external changes (like undo/redo)"""
        line = self.m_editor.GetFirstVisibleLine()
        pos = self.m_editor.GetCurrentPos()
        self.m_editor.Freeze()
        self.m_editor.SetText(self._object._content)
        self.m_editor.SetModified(False)
        try:
            self.m_editor.SetFirstVisibleLine(line)
            self.m_editor.SetCurrentPos(pos)
        except:
            pass
        self.m_editor.Thaw()

    def PreDelete(self):
        """Remove toolbar first in order to avoid gtk-collision at close"""
        #self.m_editor.Destroy()
        self.m_localToolbar.Destroy()

    def Popup(self, editor, text=None):
        """Shows a custom popup"""
        if text:
            # in the future, we need to show a complete floating dialog here
            # we receive "this->" or "object." here ..
            return
        menu = wx.Menu()
        menu.Append(self._mainframe.editProperties.GetId(),
            "test menu", "Edit relation properties")
        pos = editor.GetCurrentPos()
        p = editor.PointFromPosition(pos)
        editor.PopupMenu(menu, p)
        menu.Destroy()

    def OnNavigator(self, event):
        """Navigate throug the class structure"""
        pos = self.m_editor.GetCurrentPos()
        p = self.m_editor.PointFromPosition(pos)
        p = self.m_editor.ClientToScreen(p)
        dialog = app.ui.dlg.CodeNavigator(self, self._object)
        dialog.Move(p)
        if dialog.ShowModal() != wx.ID_OK:
            return
        pass

    def OnUndoCode(self, event):
        """Edit undo"""
        self.m_editor.Undo()

    def OnRedoCode(self, event):
        """Edit redo"""
        self.m_editor.Redo()

    def OnUpdatePasteCode(self, event):
        """Edit paste?"""
        event.Enable(self.m_editor.CanPaste())

    def OnUpdateCopyCode(self, event):
        """Edit copy?"""
        (b, e) = self.m_editor.GetSelection()
        event.Enable(b != e)

    def OnUpdateCutCode(self, event):
        """Edit cut?"""
        if self._object._readOnly:
            event.Enable(False)
        else:
            (b, e) = self.m_editor.GetSelection()
            event.Enable(b != e)

    def OnUpdateRedoCode(self, event):
        """Edit redo?"""
        if self.m_editor.CanRedo():
            event.SetText("Redo edit")
            event.Enable(True)
        else:
            event.SetText("Can't redo")
            event.Enable(False)

    def OnUpdateUndoCode(self, event):
        """Edit undo?"""
        if self.m_editor.CanUndo():
            event.SetText("Undo edit")
            event.Enable(True)
        else:
            event.SetText("Can't undo")
            event.Enable(False)

    def OnUpdateDeleteCode(self, event):
        """Edit delete?"""
        event.Enable(not self._object._readOnly)

    def Enabled(self, event):
        """Joker event"""
        event.Enable(True)

    def Disabled(self, event):
        """Joker event"""
        event.Enable(False)

    def UpdateModifiedTitle(self):
        """Update the tile after modifications"""
        if not self._fullScreen:
            i = self._notebook.GetPageIndex(self)
            s = self._notebook.GetPageText(i)
            m = '[modified] '
            if self.m_editor.IsModified():
                if s.find(m) == wx.NOT_FOUND:
                    self._notebook.SetPageText(i, m + s)
            else:
                if s.find(m) != wx.NOT_FOUND:
                    s = s.replace(m, '')
                    self._notebook.SetPageText(i, s)

    def OnEditorChange(self, event):
        """Called when editor status change"""
        if not self._fullScreen:
            self.UpdateModifiedTitle()

    @tran.TransactionalMethod('edit method')
    def Commit(self):
        """Update document"""
        text = self.m_editor.GetText()
        o = self._object
        if text == o._content:
            return False
        o.SaveState()
        o._content = text
        o.project.SetModified(True)
        k = o.inner_module or o.inner_package
        if k:
            k.ExportPythonCodeFiles()
        return True

    def OnDeleteCode(self, event):
        """Handle delete key"""
        wx.Bell()
        (b, e) = self.m_editor.GetSelection()
        if b == e:
            self.m_editor.CharRight()
        self.m_editor.DeleteBack()

    def OnCopyCode(self, event):
        """Handle a copy event"""
        self.m_editor.Copy()

    def OnPasteCode(self, event):
        """Handle a paste event"""
        self.m_editor.Paste()

    def OnCutCode(self, event):
        """Handle a paste event"""
        self.m_editor.Cut()

    def OnUpdateSaveCode(self, event):
        """Handles update event"""
        event.Enable(self.m_editor.IsModified())

    def OnSaveCode(self, event):
        """Handles save event"""
        self.Commit()
        self.m_editor.ResetModified()
        self.UpdateModifiedTitle()

    def OnFullScreen(self, event):
        """ShowFullscreen"""
        if self._fullScreen:
            self._fullScreen.LeaveFullScreen()
            wx.YieldIfNeeded()
            #self._fullScreen.Destroy()
            self._fullScreen.Close()
            self._fullScreen = None
            self.UpdateModifiedTitle()
        else:
            self._fullScreen = pane.FullScreen(self)
        self.m_editor.SetFocus()

    def handleStyleNeeded(self, event):
        """Handle scintylla events"""
        wnd = self.m_editor
        pos = wnd.GetCurrentPos()
        if pos == 0:
            return
        if wnd.GetCharAt(pos - 1) == wx.T(':'):
            lnno = wnd.GetCurrentLine()
            iden = wnd.GetLineIndentation(lnno - 1)
            wnd.SetLineIndentation(lnno, iden)

            # = self.m_editor.GetFoldLevel(lnno - 1)
        # if this is not a normal line
        #self.m_editor.SetFoldLevel(lnno,LastIndent)
        #pass


    #def AutoIdent(self, event):
    #    """Handle enter"""
    #    key = event.GetKeyCode()
    #    wnd = self.m_editor
    #    if key == wx.WXK_NUMPAD_ENTER or key == wx.WXK_RETURN:
    #        if wnd.GetCharAt(wnd.GetCurrentPos() - 1) == 58:
    #            line = wnd.GetCurrentLine() + 1
    #            wnd.SetLineIndentation(line,
    #                wnd.GetLineIndentation(line) + wnd.GetTabWidth())
    #    event.Skip()



