# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.3 on Fri May 21 21:49:10 2010

import codecs
import os.path
import cgi

import wx
from wx.stc import StyledTextCtrl

import outwiker.core.system
from outwiker.core.application import Application
from .guiconfig import EditorConfig
from outwiker.core.textprinter import TextPrinter
from .editorsearchpanel import EditorSearchPanel
from .mainid import MainId

# begin wxGlade: dependencies
# end wxGlade

# begin wxGlade: extracode

# end wxGlade

class TextEditor(wx.Panel):
    _fontConfigSection = "Font"

    def __init__(self, *args, **kwds):
        # begin wxGlade: TextEditor.__init__
        kwds["style"] = wx.TAB_TRAVERSAL
        wx.Panel.__init__(self, *args, **kwds)
        self.textCtrl = StyledTextCtrl(self, -1)
        self.searchPanel = EditorSearchPanel(self, -1)

        self.__set_properties()
        self.__do_layout()
        # end wxGlade

        self.createCoders()

        self.config = EditorConfig (Application.config)

        self.setDefaultSettings()
        self.searchPanel.setEditor (self, self.textCtrl)
        
        self.textCtrl.Bind(wx.EVT_MENU, self.onCopyFromEditor, id = MainId.ID_COPY)
        self.textCtrl.Bind(wx.EVT_MENU, self.onCutFromEditor, id = MainId.ID_CUT)
        self.textCtrl.Bind(wx.EVT_MENU, self.onPasteToEditor, id = MainId.ID_PASTE)
        self.textCtrl.Bind(wx.EVT_MENU, self.onUndo, id = MainId.ID_UNDO)
        self.textCtrl.Bind(wx.EVT_MENU, self.onRedo, id = MainId.ID_REDO)
        self.textCtrl.Bind (wx.EVT_CHAR, self.OnChar_ImeWorkaround)
        self.textCtrl.Bind (wx.EVT_KEY_DOWN, self.onKeyDown)


    def Print (self):
        selectedtext = self.textCtrl.GetSelectedText()
        text = self.textCtrl.GetText()

        printer = TextPrinter (self)
        printer.printout (text if len (selectedtext) == 0 else selectedtext)


    def onCopyFromEditor (self, event):
        self.textCtrl.Copy()


    def onCutFromEditor (self, event):
        self.textCtrl.Cut()


    def onPasteToEditor (self, event):
        self.textCtrl.Paste()

    
    def onUndo (self, event):
        self.textCtrl.Undo()
    
    def onRedo (self, event):
        self.textCtrl.Redo()


    def __set_properties(self):
        # begin wxGlade: TextEditor.__set_properties
        pass
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: TextEditor.__do_layout
        mainSizer = wx.FlexGridSizer(2, 1, 0, 0)
        mainSizer.Add(self.textCtrl, 1, wx.EXPAND, 0)
        mainSizer.Add(self.searchPanel, 1, wx.EXPAND, 0)
        self.SetSizer(mainSizer)
        mainSizer.Fit(self)
        mainSizer.AddGrowableRow(0)
        mainSizer.AddGrowableCol(0)
        # end wxGlade

        self.searchPanel.Hide()
        self.Layout()
    

    def setDefaultSettings (self):
        """
        Установить шрифт по умолчанию в контрол StyledTextCtrl
        """
        size = self.config.fontSize.value
        faceName = self.config.fontName.value
        isBold = self.config.fontIsBold.value
        isItalic = self.config.fontIsItalic.value

        self.textCtrl.StyleClearAll()

        self.textCtrl.StyleSetSize (wx.stc.STC_STYLE_DEFAULT, size)
        self.textCtrl.StyleSetFaceName (wx.stc.STC_STYLE_DEFAULT, faceName)
        self.textCtrl.StyleSetBold (wx.stc.STC_STYLE_DEFAULT, isBold)
        self.textCtrl.StyleSetItalic (wx.stc.STC_STYLE_DEFAULT, isItalic)
        
        self.textCtrl.StyleSetSize (0, size)
        self.textCtrl.StyleSetFaceName (0, faceName)
        self.textCtrl.StyleSetBold (0, isBold)
        self.textCtrl.StyleSetItalic (0, isItalic)
        
        # Заблокируем горячую клавишу Ctrl+D, чтобы использовать ее как добавление закладки
        self.textCtrl.CmdKeyClear (ord ("D"), wx.stc.STC_SCMOD_CTRL)
        self.textCtrl.CmdKeyClear (ord ("R"), wx.stc.STC_SCMOD_CTRL | wx.stc.STC_SCMOD_SHIFT)
        self.textCtrl.SetWrapMode (wx.stc.STC_WRAP_WORD)
        self.textCtrl.SetWrapVisualFlags (wx.stc.STC_WRAPVISUALFLAG_END)

        self._setMarginWidth (self.textCtrl)
        self.textCtrl.SetTabWidth (self.config.tabWidth.value)
    

    def _setMarginWidth (self, editor):
        """
        Установить размер левой области, где пишутся номера строк в зависимости от шрифта
        """
        linenumbers =  self.config.lineNumbers.value
        fontSize = self.config.fontSize.value

        if linenumbers:
            width = int (35.0 / 10.0 * fontSize)
            editor.SetMarginWidth (0, width)
            editor.SetMarginWidth (1, 5)
        else:
            editor.SetMarginWidth (0, 0)
            editor.SetMarginWidth (1, 8)
    

    def calcByteLen(self, text):
        """Посчитать длину строки в байтах, а не в символах"""
        return len(self.encoder(text)[0])


    def calcBytePos (self, text, pos):
        """Преобразовать позицию в символах в позицию в байтах"""
        return len(self.encoder (text[: pos] )[0] )


    def createCoders (self):
        encoding = outwiker.core.system.getOS().inputEncoding

        self._mbcsDec = codecs.getdecoder(encoding)
        self.mbcsEnc = codecs.getencoder(encoding)
        self.encoder = codecs.getencoder("utf-8")
    

    def onKeyDown (self, event):
        key = event.GetKeyCode()

        if key == wx.WXK_ESCAPE:
            self.searchPanel.Close()

        event.Skip()


    def OnChar_ImeWorkaround(self, evt):
        """
        Обработка клавиш вручную, чтобы не было проблем с вводом русских букв в Linux.
        Основа кода взята из Wikidpad (WikiTxtCtrl.py -> OnChar_ImeWorkaround)
        """
        key = evt.GetKeyCode()


        # Return if this doesn't seem to be a real character input
        if evt.ControlDown() or (0 < key < 32):
            evt.Skip()
            return
            
        if key >= wx.WXK_START and evt.GetUnicodeKey() != key:
            evt.Skip()
            return

        unichar = unichr(evt.GetUnicodeKey())

        self.textCtrl.ReplaceSelection(self.mbcsEnc (unichar, "replace")[0])


    def AddText (self, text):
        self.textCtrl.AddText (text)


    def replaceText (self, text):
        self.textCtrl.ReplaceSelection (text)


    def turnText (self, lefttext, righttext):
        selText = self.textCtrl.GetSelectedText()
        newtext = lefttext + selText + righttext
        self.textCtrl.ReplaceSelection (newtext)

        if len (selText) == 0:
            """
            Если не оборачиваем текст, а делаем пустой тег, то поместим каретку до закрывающегося тега
            """
            currPos = self.textCtrl.GetSelectionEnd()
            len_bytes = self.calcByteLen (righttext)

            newPos = currPos - len_bytes

            self.textCtrl.SetSelection (newPos, newPos)


    def escapeHtml (self, event):
        selText = self.textCtrl.GetSelectedText()
        text = cgi.escape (selText, quote=True)
        self.textCtrl.ReplaceSelection (text)


    def SetReadOnly (self, readonly):
        self.textCtrl.SetReadOnly (readonly)


    def GetText(self):
        return self.textCtrl.GetText()


    def SetText (self, text):
        self.textCtrl.SetText (text)


    def EmptyUndoBuffer (self):
        self.textCtrl.EmptyUndoBuffer()


    def GetSelectedText (self):
        return self.textCtrl.GetSelectedText()

# end of class TextEditor


