#!/usr/bin/env python

import wx
import sys
import qterm
import os
import time
import stat
import re

editor = [ "gvim", "--servername", "It's All Text!",
           "--remote-wait-silent" ]

def StripLine(s):
    head = s[0:2]
    if head == ': ' or head == '> ':
        return head + s[2:].rstrip()
    else:
        return s.rstrip()

def DownloadArticle(lp):
    edit_re = re.compile('.....*Ctrl-Q.*\[(\d+),(\d+)\].*\d\d:\d\d')
    delay = 10 # In 100ms, like LILO.

    lp = long(sys.argv[0])
    article_buf = []

    status_line = qterm.getText(lp, qterm.rows(lp) - 1)
    status_match = edit_re.match(status_line)
    if not status_match:
        return qterm.copyArticle(lp)
    else:
        old_caret_row = -1
        life = delay
        def get_caret_row(lp):
            status_line = qterm.getText(lp, qterm.rows(lp) - 1)
            status_match = edit_re.match(status_line)
            if status_match:
                return int(status_match.group(1))
            else:
                return None
        while True:
            caret_row = get_caret_row(lp)
            while caret_row == old_caret_row:
                if life <= 0:
                    break
                time.sleep(0.1)
                life -= 1
                caret_row = get_caret_row(lp)
            if life <= 0:
                break
            else:
                life = delay
            for i in xrange(0, qterm.rows(lp) - 2):
                article_buf.append(qterm.getText(lp, i))
            old_caret_row = caret_row
            qterm.sendString(lp, '\033[6~')
        article_buf = map(lambda x: StripLine(x),
            article_buf[:-(qterm.rows(lp) - 2)])
    return reduce(lambda x, y: x + os.linesep + y, article_buf)

def ReplyGvim(reply_model, signature, composing):
    lp = long(sys.argv[0])

    qterm.sendParsedString(lp, "rrr^h^h")
    qterm.sendString(lp, reply_model + "\n0\n\n")
    time.sleep(2)
    article = DownloadArticle(lp)
    qterm.sendParsedString(lp, "^xa\n\n")
    if composing:
        qterm.sendParsedString(lp, "rr^h")
        qterm.sendString(lp, "n\n" + signature + "\n\n")

    filename = os.tempnam() + ".bbs"
    f = file(filename, "w")
    f.write(re.sub('\n*(\n~)*\Z', '', article) + "\n")
    f.close()

    mtime = os.stat(filename)[stat.ST_MTIME]

    os.spawnvp(os.P_WAIT, editor[0], editor + [ filename ])

    if os.stat(filename)[stat.ST_MTIME] > mtime:
        f = file(filename, "r")
        content = f.read()
        if not composing:
            qterm.sendParsedString(lp, "rr^h")
            qterm.sendString(lp, "n\n" + signature + "\n\n")
        qterm.sendString(lp, content[ : -1])
        qterm.sendParsedString(lp, "^x\n")
    else:
        if composing:
            qterm.sendParsedString(lp, "^xa\n")

    os.remove(filename)

class ReplyGVimDialog(wx.Dialog):
    def __init__(self, *args, **kwds):
        # begin wxGlade: ReplyGVimDialog.__init__
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
        wx.Dialog.__init__(self, *args, **kwds)
        self.label_1 = wx.StaticText(self, -1, _("Reply mode: "))
        self.chcReplyMode = wx.Choice(self, -1, choices=[_("S"), _("Y"), _("N"), _("R"), _("A")])
        self.label_2 = wx.StaticText(self, -1, _("Signature: "))
        self.chcSignature = wx.Choice(self, -1, choices=[_("No Signature"), _("Random Signature"), _("Signature 1"), _("Signature 2"), _("Signature 3"), _("Signature 4"), _("Signature 5"), _("Signature 6")])
        self.chkComposing = wx.CheckBox(self, -1, _("Enter replying mode when composing"))
        self.btnOK = wx.Button(self, -1, _("&OK"))
        self.btnCancel = wx.Button(self, -1, _("&Cancel"))

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.OnOK, self.btnOK)
        self.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel)
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: ReplyGVimDialog.__set_properties
        self.SetTitle(_("Reply GVim for QTerm"))
        self.chcReplyMode.SetSelection(0)
        self.chcSignature.SetSelection(1)
        self.chkComposing.SetToolTipString(_("Useful for uploading attachment"))
        self.btnOK.SetDefault()
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: ReplyGVimDialog.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_4.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
        sizer_4.Add(self.chcReplyMode, 0, wx.ADJUST_MINSIZE, 0)
        sizer_2.Add(sizer_4, 0, wx.ALL|wx.EXPAND, 5)
        sizer_5.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
        sizer_5.Add(self.chcSignature, 0, wx.ADJUST_MINSIZE, 0)
        sizer_2.Add(sizer_5, 0, wx.ALL|wx.EXPAND, 5)
        sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
        sizer_1.Add(self.chkComposing, 0, wx.ALL|wx.ADJUST_MINSIZE, 5)
        sizer_3.Add(self.btnOK, 0, wx.ADJUST_MINSIZE, 0)
        sizer_3.Add(self.btnCancel, 0, wx.ADJUST_MINSIZE, 0)
        sizer_1.Add(sizer_3, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 0)
        self.SetSizer(sizer_1)
        sizer_1.Fit(self)
        self.Layout()
        # end wxGlade

    def OnOK(self, event): # wxGlade: ReplyGVimDialog.<event_handler>
        global r, s, c
        r = ('s','y','n','r','a')[self.chcReplyMode.GetSelection()]
        s = ('0','l','1','2','3','4','5','6')[self.chcSignature.GetSelection()]
        c = self.chkComposing.IsChecked()
        self.Destroy()

    def OnCancel(self, event): # wxGlade: ReplyGVimDialog.<event_handler>
        r = ""
        s = ""
        self.Destroy()

import gettext
gettext.install("app") # replace with the appropriate catalog name

r = ""
s = ""
c = False
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
dialog = ReplyGVimDialog(None, -1, "")
app.SetTopWindow(dialog)
dialog.Show()
app.MainLoop()
if len(r) > 0:
    ReplyGvim(r, s, c)
