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

#import wx


MARGIN_LINE_NUMBERS = 0
MARGIN_FOLD = 1

import wx
import wx.stc
import wx.lib.newevent
from ctx import theContext as context
import tran
from app.ui import pane
from activity.models.ui import ui as ui


#define update sash required event
UglySashEvent, EVT_UGLY_SASH = wx.lib.newevent.NewEvent()

LocalCommand, EVT_LOCAL_COMMAND_EVENT = wx.lib.newevent.NewCommandEvent()

CLOSE_PANE_ID = wx.ID_HIGHEST + 100


# Implementing ConstructorPane
class ConstructorPane(ui.ConstructorPane):
    """Pane for constructor edition"""
    def __init__(self, parent, mainframe, constructor):
        """Initialization"""
        super(ConstructorPane, self).__init__(parent)
        self._mainframe = mainframe
        self._object = constructor
        self._notebook = parent
        self._bodyTouched = False

        self._types = dict([(x._name, x) for x in constructor.types])
        self.m_editor.SetText(constructor._content)
        self.m_init.SetText(constructor._init)
        self.m_editor.Initialize(self._types)
        self.m_init.Initialize(self._types)
        self.RecalcSashPos()

        frame = context.frame
        #bind some messages to this frame
        self.Bind(wx.EVT_MENU, frame.CloseCurrentDocPane, id=CLOSE_PANE_ID)
        self.Bind(wx.EVT_MENU, self.OnDeleteCode, id=self.m_delete.GetId())
        self.Bind(wx.EVT_MENU, self.OnUndoCode, id=frame.undo.GetId())
        self.Bind(wx.EVT_MENU, self.OnRedoCode, id=frame.redo.GetId())
        self.Bind(wx.EVT_MENU, self.OnCopyCode, id=frame.copy.GetId())
        self.Bind(wx.EVT_MENU, self.OnPasteCode, id=frame.paste.GetId())
        self.Bind(wx.EVT_MENU, self.OnCutCode, id=frame.cut.GetId())
        self.Bind(wx.EVT_MENU, self.OnSaveCode, id=frame.saveProject.GetId())

        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateDeleteCode, id=self.m_delete.GetId())
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUndoCode, id=frame.undo.GetId())
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateRedoCode, id=frame.redo.GetId())
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateCopyCode, id=frame.copy.GetId())
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdatePasteCode, id=frame.paste.GetId())
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateCutCode, id=frame.cut.GetId())
        self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateSaveCode, id=frame.saveProject.GetId())

        self._selected = None
        self.m_editor.popup_handler = self
        self.m_init.popup_handler = self
        self._fullScreen = None

        wx.stc.EVT_STC_CHANGE(self.m_editor, self.m_editor.GetId(),
             self.OnEditorChange)
        wx.stc.EVT_STC_CHANGE(self.m_init, self.m_init.GetId(), self.OnInitChange)

        wx.stc.EVT_STC_ZOOM(self.m_editor, self.m_editor.GetId(),
            self.OnEditorZoomed)
        wx.stc.EVT_STC_ZOOM(self.m_init, self.m_init.GetId(),
            self.OnInitZoomed)

        EVT_UGLY_SASH(self, self.OnUglySash)

        aTable = wx.AcceleratorTable([
            wx.AcceleratorEntry(wx.ACCEL_ALT | wx.ACCEL_CTRL, ord('F'), ui.ID_TOGGLE_FULLSCREEN),
            wx.AcceleratorEntry(wx.ACCEL_CTRL, ord('W'), CLOSE_PANE_ID),
            wx.AcceleratorEntry(wx.ACCEL_CTRL, ord('S'), frame.saveProject.GetId()),
            wx.AcceleratorEntry(wx.ACCEL_NORMAL, wx.WXK_DELETE, self.m_delete.GetId())
        ])
        self.SetAcceleratorTable(aTable)

    def Refresh(self):
        """Update editor from external changes (like undo/redo)"""
        line = self.m_init.GetFirstVisibleLine()
        pos = self.m_init.GetCurrentPos()
        self.m_init.Freeze()
        self.m_init.SetText(self._object._init)
        self.m_init.SetModified(False)
        try:
            self.m_init.SetFirstVisibleLine(line)
            self.m_init.SetCurrentPos(pos)
        except:
            pass
        self.m_init.Thaw()
        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_init.Destroy()
        self.m_auiToolBar5.Destroy()

    def Popup(self, editor, text=None):
        """Called from editor to show user menus"""
        pass

    def OnInitPane(self):
        """Initialization"""
        self.RecalcSashPos()

    def RecalcSashPos(self):
        """Take amodelount of init section and recalc sash"""
        h = 10
        if self.m_init.GetLineCount():
            h += (self.m_init.GetLineCount() + 1) * (self.m_init.TextHeight(0) +
                self.m_init.GetExtraAscent() +
                self.m_init.GetExtraDescent())
        #self.m_splitter2.SetMinimumPaneSize(h)
        self.m_splitter2.SetSashPosition(h, True)
        self.Layout()
        self.m_splitter2.UpdateSize()

    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() or self.m_init.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"""
        self.UpdateModifiedTitle()

    def OnInitChange(self, event):
        """Called when editor status change"""
        self.RecalcSashPos()
        self.UpdateModifiedTitle()

    def OnUglySash(self, event):
        """Recalc sash"""
        sz = event.source.GetZoom()
        tz = event.target.GetZoom()
        if sz != tz:
            event.target.SetZoom(sz)
            wx.PostEvent(self, event)
        else:
            self.RecalcSashPos()

    def OnEditorZoomed(self, event):
        """Called when the UI of the editor changes"""
        e = UglySashEvent(source=self.m_editor, target=self.m_init)
        wx.PostEvent(self, e)
        event.Skip()

    def OnInitZoomed(self, event):
        """Called when the UI of the init par changes"""
        e = UglySashEvent(source=self.m_init, target=self.m_editor)
        wx.PostEvent(self, e)
        event.Skip()

    @tran.TransactionalMethod('edit constructor')
    def Commit(self):
        """Update document"""
        text = self.m_editor.GetText()
        init = self.m_init.GetText()
        o = self._object
        if text == o._content and init == o._init:
            return False
        if text != o._content:
            o._bodyTouched = True
        if init != o._content:
            o._initTouched = True
        o.SaveState()
        o._content = text
        o._init = init
        o.project.SetModified(True)
        k = o.outer_class or o.outer_module
        if k:
            k.ExportCppCodeFiles(force=True)
        return True

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

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

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

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

    def OnUpdateCopyCode(self, event):
        """Edit copy?"""
        if self._selected:
            (b, e) = self._selected.GetSelection()
            event.Enable(b != e)
        else:
            event.Enable(False)

    def OnUpdatePasteCode(self, event):
        """Edit paste?"""
        event.Enable(bool(self._selected and self._selected.CanPaste()))

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

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

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

    def OnDeleteCode(self, event):
        """Handle delete for focus editor"""
        if self._selected is None:
            return
        (b, e) = self._selected.GetSelection()
        if b == e:
            self._selected.CharRight()
        self._selected.DeleteBack()

    def OnCopyCode(self, event):
        """Handle copy for focus editor"""
        if self._selected is None:
            return
        self._selected.Copy()

    def OnPasteCode(self, event):
        """Handle paste for focus editor"""
        if self._selected is None:
            return
        self._selected.Paste()

    def OnCutCode(self, event):
        """Handle paste for focus editor"""
        if self._selected is None:
            return
        self._selected.Cut()

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

    def OnFullScreen(self, event):
        """ShowFullscreen"""
        curs = self._selected
        if self._fullScreen:
            self._fullScreen.LeaveFullScreen()
            self._fullScreen.Destroy()
            self._fullScreen = None
            self.UpdateModifiedTitle()
        else:
            self._fullScreen = pane.FullScreen(self)
        if curs:
            curs.SetFocus()

    def OnInitLeaveFocus(self, event):
        "Handle LeaveFocus event for init"
        self._selected = None
        event.Skip()

    def OnInitGetFocus(self, event):
        "Handle GetFocus event for init"
        self._selected = self.m_init
        event.Skip()

    def OnEditorLeaveFocus(self, event):
        "Handle LeaveFocus event for editor"
        self._selected = None
        event.Skip()

    def OnEditorGetFocus(self, event):
        "Handle GetFocus event for editor"
        self._selected = self.m_editor
        event.Skip()

