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

import wx
import wxx
import wx.stc
from ctx import theContext as context
import tran
import tran.TransactionStack as stack
from app.ui.pane import BasePane
from activity.files.ui import ui as ui
from activity.models.ui import ui as amui

CLOSE_PANE_ID = wx.ID_HIGHEST + 100


# Implementing FilePane
class FilePythonPane(BasePane, ui.FilePythonPane):
    """Implements code editor"""
    def __init__(self, parent, mainframe, fileobj):
        """Intialization of method editor"""
        super(FilePythonPane, self).__init__(parent)
        self._parent = parent
        self._mainframe = mainframe
        self._object = fileobj
        self._types = {}
        self._defaulBkColor = self.GetBackgroundColour()
        self.m_editor.SetText(fileobj.GetText())
        self.m_editor.HandleBreakpoints(fileobj.breakpoints)
        self.m_editor.HandleBookmarks(fileobj.bookmarks)
        self.m_editor.EnableBreakpoints(True)
        self.m_editor.EnableBookmarks(True)
        self.m_editor.Initialize(self._types)
        self.m_editor.SetReadOnly(fileobj._readOnly)
        # setup mark zone for python
        self.m_editor.SetEdgeMode(wx.stc.STC_EDGE_BACKGROUND)
        self.m_editor.SetEdgeColumn(80)
        self.Layout()

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

        frame = context.frame
        self.BindSpecial(wx.EVT_MENU, handler=frame.CloseCurrentDocPane, id=CLOSE_PANE_ID)
        self.BindSpecial(wx.EVT_MENU, self.OnDelete, id=frame.delete.GetId())
        self.BindSpecial(wx.EVT_MENU, self.OnSave, id=frame.saveProject.GetId())
        self.BindSpecial(wx.wx.EVT_UPDATE_UI, self.OnUpdateSave, id=frame.saveProject.GetId())

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

    @property
    def breakpoint(self):
        """return info about if the current line holds breakpoint"""
        return self.m_editor.breakpoint

    def ToggleBreakpoint(self, event):
        """toggle breakpoint"""
        self.m_editor.ToggleBreakpoint(event)

    @property
    def line(self):
        """return current line"""
        return self.m_editor.GetCurrentLine()

    def SetReadOnly(self, value=True):
        """Set readonly flag. Used for debug"""
        self.m_editor.SetReadOnly(value)

    def RestoreReadOnly(self):
        """Set readonly flag"""
        self.m_editor.SetReadOnly(self._object._readOnly)

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

    def OnEditorChange(self, event):
        """Called when editor status change"""
        if self.m_editor.GetModify():
            self.SetBackgroundColour(wx.LIGHT_GREY)
        else:
            self.SetBackgroundColour(self._defaulBkColor)

    def GotoLine(self, line, select=False):
        """Called for goto to line"""
        self.m_editor.GotoLine(line, select)

    def DebugLine(self, line):
        """"""
        self.m_editor.GotoLine(line, False)
        start = self.m_editor.PositionFromLine(line)
        length = self.m_editor.LineLength(line)
        self.m_editor.StartStyling(start, 32)
        self.m_editor.SetStyling(length, 32)
        if hasattr(self, '_debugLine'):
            if self._debugLine != line:
                self.m_editor.GotoLine(self._debugLine, False)
                start = self.m_editor.PositionFromLine(self._debugLine)
                length = self.m_editor.LineLength(self._debugLine)
                self.m_editor.StartStyling(start, 32)
                self.m_editor.SetStyling(length, 0)
        self._debugLine = line

    def Select(self, sline, scol, eline, ecol):
        """Called for select range"""
        self.m_editor.Select(sline, scol, eline, ecol)

    @tran.TransactionalMethod()
    def Commit(self):
        """Do commit changes"""
        if self.m_editor.GetModify():
            self._object.SaveState()
            self._object.SetText(self.m_editor.GetText())
            self.m_editor.SetModified(False)
            self.SetBackgroundColour(self._defaulBkColor)
            stack.instance.SetName('modify file {}'.format(self._object._name))
            return True
        else:
            return False

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

    def OnUpdateSave(self, event):
        """Handles update event"""
        if not self.is_event_handler:
            print "Called on inactive window"
            event.Skip()
            return
        if self.FindFocus() == self.m_editor:
            event.Enable(self.m_editor.GetModify())
        else:
            event.Skip()

    def OnSave(self, event):
        """Handles save event"""
        if self.FindFocus() == self.m_editor:
            self.Commit()
        else:
            event.Skip()


