#!/usr/bin/python
# -*- coding: utf-8 -*-
# SlideSword
# Author: DarkRanger <http://darkranger.no-ip.org/>
# License: GNU General Public License

import os, sys, re
import datetime, time
import codecs
import shutil
import Sword

from PySide.QtCore import *
from PySide.QtGui import *

PRODUCT_NAME = u"SlideSword"
VERSION = u"beta 0.2"
BUILD = u"20141128"
DEFAULT_WIDTH = 220
DEFAULT_HEIGHT = 260
DEFAULT_FONT = "PMingLiU"
ENCODING = "utf-8"
JS_DIR = "js"
JS_JQUERY = "jquery-1.10.2.min.js"
JS_MOUSEWHEEL = "jquery.mousewheel.js"
JS_SLIDESWORD = "slidesword.js"

HTML_EXT = [".htm", ".html", ".xhtml"]

OT_BOOKS = [u"創世記",  u"出埃及記", u"利未記", u"民數記", u"申命記", u"約書亞記", u"士師記", u"路得記", u"撒母耳記上", u"撒母耳記下", \
            u"列王紀上", u"列王紀下", u"歷代志上", u"歷代志下", u"以斯拉記", u"尼希米記", u"以斯帖記", u"約伯記", u"詩篇", u"箴言", \
            u"傳道書", u"雅歌", u"以賽亞書", u"耶利米書", u"耶利米哀歌", u"以西結書", u"但以理書", u"何西阿書", u"約珥書", u"阿摩司書", \
            u"俄巴底亞書", u"約拿書", u"彌迦書", u"那鴻書", u"哈巴谷書", u"西番雅書", u"哈該書", u"撒迦利亞書", u"瑪拉基書"]

NT_BOOKS = [u"馬太福音", u"馬可福音", u"路加福音", u"約翰福音", u"使徒行傳", u"羅馬書", u"哥林多前書", u"哥林多後書", u"加拉太書", u"以弗所書", \
            u"腓立比書", u"歌羅西書", u"帖撒羅尼迦前書", u"帖撒羅尼迦後書", u"提摩太前書", u"提摩太後書", u"提多書", u"腓利門書", u"希伯來書", u"雅各書", \
            u"彼得前書", u"彼得後書", u"約翰一書", u"約翰二書", u"約翰三書", u"猶大書", u"啟示錄"]
            
OT_INDEXES = ["Gen", "Exod", "Lev", "Num", "Deut", "Josh", "Judg", "Ruth", "1Sam", "2Sam", \
              "1Kgs", "2Kgs", "1Chr", "2Chr", "Ezra", "Neh", "Esth", "Job", "Ps", "Prov", \
              "Eccl", "Song", "Isa", "Jer", "Lam", "Ezek", "Dan", "Hos", "Joel", "Amos", \
              "Obad", "Jonah", "Mic", "Nah", "Hab", "Zeph", "Hag", "Zech", "Mal" ]

NT_INDEXES = ["Matt", "Mark", "Luke", "John", "Acts", "Rom", "1Cor", "2Cor", "Gal", "Eph", \
              "Phil", "Col", "1Thess", "2Thess", "1Tim", "2Tim", "Titus", "Phlm", "Heb", "Jas", \
              "1Pet", "2Pet", "1John", "2John", "3John", "Jude", "Rev"]
              
appdir = os.path.abspath(os.path.dirname(sys.argv[0])).decode(sys.getfilesystemencoding())
os.chdir(appdir)

def getVersions():
    versions = []
    modulePath = os.path.join(appdir, u"modules", u"texts", u"ztext")
    if os.path.isdir(modulePath):
        for fn in os.listdir(modulePath):
            if os.path.isdir(os.path.join(modulePath, fn)):
                versions.append(fn)
    return versions

def checkScriptFile():
    if not os.path.isfile(os.path.join(appdir, JS_DIR, JS_JQUERY)):
        return False
    if not os.path.isfile(os.path.join(appdir, JS_DIR, JS_MOUSEWHEEL)):
        return False
    if not os.path.isfile(os.path.join(appdir, JS_DIR, JS_SLIDESWORD)):
        return False
    return True

def copyScriptFile(targetPath):
    if checkScriptFile():
        shutil.copy2(os.path.join(appdir, JS_DIR, JS_JQUERY), os.path.join(targetPath, JS_JQUERY))
        shutil.copy2(os.path.join(appdir, JS_DIR, JS_MOUSEWHEEL), os.path.join(targetPath, JS_MOUSEWHEEL))

def stringToInt(string):
    return int(re.match("[0-9]+", string).group(0))

def slideSword(version, templatePath, book, title, chapter, beginVerse, totalVerses):
    try:
        templateFile = codecs.open(templatePath, "r", ENCODING)
        originalFullText = templateFile.read()
        templateFile.close()
    
        slideScriptFile = codecs.open(os.path.join(appdir, JS_DIR, JS_SLIDESWORD), "r", ENCODING)
        slideScript = slideScriptFile.read()
        slideScriptFile.close()

        bibleVerses = ""
        for x in range (0, totalVerses):
            word = Sword.result(version, book, chapter, str(beginVerse + x))
            if word:
                bibleVerses = bibleVerses + ("\"%s\", " % word.decode(ENCODING))
            else:
                if x == 0:
                    bibleVerses = bibleVerses + (u"\"無內容\", ")
                break
        bibleVerses = "[%s]" % bibleVerses
        slideScript = slideScript.replace("{{bible-verses}}", bibleVerses)
        slideScript = slideScript.replace("{{book-chapter}}", "\"%s %s\"" % (title, chapter))
        slideScript = slideScript.replace("{{verse-begin}}", "%d" % beginVerse)
    
        newFullText = originalFullText
        bodyElement = re.search("(<body[^<>]*>)", newFullText)
        if bodyElement:
            newFullText = newFullText.replace(bodyElement.group(0), "%s\n<script type=\"text/javascript\">\n%s\n</script>" % (bodyElement.group(0), slideScript))
        newFullText = newFullText.replace("</head>", "<script src=\"%s\"></script>\n<script src=\"%s\"></script>\n</head>" % (JS_JQUERY, JS_MOUSEWHEEL))
    
        now = time.localtime()
        date = time.strftime("%Y-%m%d-%H%M%S", now)
        newPath = "%s_%s%s" % (os.path.splitext(templatePath)[0], date, os.path.splitext(templatePath)[1])
        htmlFile = codecs.open(newPath, "w", ENCODING)
        htmlFile.write(newFullText)
        htmlFile.close()
        copyScriptFile(os.path.dirname(templatePath))
        
    except Exception, error:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        print "%s:%d: %s" % (os.path.split(exc_tb.tb_frame.f_code.co_filename)[1], exc_tb.tb_lineno, error)
        return False
        
    return True

def txtSword(version, book, title, chapter, beginVerse, totalVerses):
    try:
        now = time.localtime()
        date = time.strftime("%Y-%m%d-%H%M%S", now)
        txtPath = "%s.txt" % date
        txtFile = codecs.open(txtPath, "w", ENCODING)
        txtFile.write(u"\uFEFF")
        txtFile.write("%s %s\r\n" % (title, chapter))
        for x in range (0, totalVerses):
            word = Sword.result(version, book, chapter, str(beginVerse + x))
            if word:
                txtFile.write("%d\r\n%s\r\n" % (beginVerse + x, word.decode(ENCODING)))
            else:
                if x == 0:
                    txtFile.write(u"無內容\r\n")
                break
        txtFile.close()

    except Exception, error:
        exc_type, exc_obj, exc_tb = sys.exc_info()
        print "%s:%d: %s" % (os.path.split(exc_tb.tb_frame.f_code.co_filename)[1], exc_tb.tb_lineno, error)
        return False
        
    return True


class Dialog(QDialog):
    def __init__(self):
        super(Dialog, self).__init__()
        super(Dialog, self).setWindowFlags(Qt.WindowSystemMenuHint | Qt.WindowTitleHint)
        self.initUI()
        
    def initUI(self):         
        self.setFixedSize(250, 200)
        self.setWindowTitle(u"關於 %s" % PRODUCT_NAME)
        self.vbox = QGridLayout()
        self.setFont(DEFAULT_FONT)

        self.aboutEdit = QTextEdit()
        self.aboutEdit.setReadOnly(True)
        contexts = ("<b>%s</b><br>" % PRODUCT_NAME, \
                    "%s %s<br>" % (VERSION, BUILD), \
                    "DarkRanger<br>&lt;darkranger.no-ip.org&gt;<br><br>", \
                    u"本工具包含<br>由下列人士/社群所發佈的元件:<br><br>", \
                    "<b>The SWORD Project</b><br>", \
                    "&lt;www.crosswire.org&gt;<br><br>"                    
                    "<b>pysword</b><br>" , \
                    "Kenneth Arnold<br>&lt;github.com/kcarnold/pysword&gt;<br><br>")
        message = "\n".join(contexts)
        self.aboutEdit.setHtml(message)
                     
        self.aboutEdit.setAlignment(Qt.AlignCenter)
        self.vbox.addWidget(self.aboutEdit, 0,0,1,3)
        
        self.closeButton = QPushButton(u"關閉")
        self.closeButton.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
        self.vbox.addWidget(self.closeButton, 1,1,1,3)
        self.closeButton.clicked.connect(self.closeButtonPushed)
        
        self.setLayout(self.vbox)        
        self.show()
        
    def closeButtonPushed(self):
        self.close()
        
class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()      
        
    def initUI(self):
        self.qr = self.frameGeometry()
        self.cp = QDesktopWidget().availableGeometry().center()
        self.qr.moveCenter(self.cp)
        self.move(self.qr.topLeft())
        self.vbox = QGridLayout()
        self.setFont(DEFAULT_FONT)
        
        self.ot = QRadioButton(u"舊約")
        self.vbox.addWidget(self.ot, 0,0,1,3)
        
        self.nt = QRadioButton(u"新約")
        self.vbox.addWidget(self.nt, 0,2,1,3)
        
        self.bookCombo = QComboBox(self)
        self.vbox.addWidget(self.bookCombo, 1,0,1,6)
        
        self.chapterEdit = QLineEdit()
        self.vbox.addWidget(self.chapterEdit, 2,0,1,1)
        self.chapterLabel = QLabel(u"章")
        self.vbox.addWidget(self.chapterLabel, 2,1,1,1)
        self.beginEdit = QLineEdit()
        self.vbox.addWidget(self.beginEdit, 2,2,1,1)
        self.dashLabel = QLabel(u"-")
        self.vbox.addWidget(self.dashLabel, 2,3,1,1)
        self.endEdit = QLineEdit()
        self.vbox.addWidget(self.endEdit, 2,4,1,1)
        self.verseLabel = QLabel(u"節")
        self.vbox.addWidget(self.verseLabel, 2,5,1,1)
        
        self.versionCombo = QComboBox(self)
        self.vbox.addWidget(self.versionCombo, 3,0,1,6)
        versions = getVersions()
        for version in versions:
            self.versionCombo.addItem(version)
        
        self.templateEdit = QLineEdit()
        self.templateEdit.setPlaceholderText(u"網頁範本路徑")
        self.vbox.addWidget(self.templateEdit, 4,0,1,3)
        self.templateButton = QPushButton(u"選擇")
        self.vbox.addWidget(self.templateButton, 4,3,1,3)
        
        self.generateButton = QPushButton(u"產出網頁")
        self.vbox.addWidget(self.generateButton, 5,0,1,6)

        self.generateTxtButton = QPushButton(u"產出文字檔")
        self.vbox.addWidget(self.generateTxtButton, 6,0,1,6)
        
        self.aboutButton = QPushButton(u"關於")
        self.vbox.addWidget(self.aboutButton, 7,0,1,6)
        
        self.connect(self.ot, SIGNAL("toggled(bool)"), self.otToggled)
        self.connect(self.nt, SIGNAL("toggled(bool)"), self.ntToggled)
        self.connect(self.templateButton, SIGNAL("clicked()"), self.templateButtonPushed)
        self.connect(self.generateButton, SIGNAL("clicked()"), self.generateButtonPushed)
        self.connect(self.generateTxtButton, SIGNAL("clicked()"), self.generateTxtButtonPushed)
        self.connect(self.aboutButton, SIGNAL("clicked()"), self.aboutButtonPushed)
        self.connect(self.chapterEdit, SIGNAL("returnPressed()"), self.generateButtonPushed)
        self.connect(self.beginEdit, SIGNAL("returnPressed()"), self.generateButtonPushed)
        self.connect(self.endEdit, SIGNAL("returnPressed()"), self.generateButtonPushed)
        self.connect(self.templateEdit, SIGNAL("returnPressed()"), self.generateButtonPushed)
        
        self.setLayout(self.vbox)
        self.ot.toggle()
        self.ot.setFocus()
        self.setAcceptDrops(True)
        
    def otToggled(self, toggled):
        if toggled:
            self.bookCombo.clear()
            for x in range (0, 39):
                self.bookCombo.addItem(OT_BOOKS[x])
       
    def ntToggled(self, toggled):
        if toggled:
            self.bookCombo.clear()
            for x in range (0, 27):
                self.bookCombo.addItem(NT_BOOKS[x])
                
    def templateButtonPushed(self):
        fn, _ = QFileDialog.getOpenFileName(self, None, None, "HTML file (*.htm *.html *.xhtml)")
        if fn:
            self.templateEdit.setText(os.path.abspath(fn))

    def generateButtonPushed(self):
        if not checkScriptFile():
            self.msb = QMessageBox.information(self, u"訊息", u"找不到所需的 JavaScript, 操作終止")
        elif self.versionCombo.currentText() == "":
            self.msb = QMessageBox.information(self, u"訊息", u"找不到聖經檔, 操作終止")
        elif not os.path.isfile(self.templateEdit.text()):
            self.msb = QMessageBox.information(self, u"訊息", u"無效的路徑, 操作終止")
        elif re.match("[0-9]+", self.chapterEdit.text()) and re.match("[0-9]+", self.beginEdit.text()):
            if self.ot.isChecked():
                book = OT_INDEXES[self.bookCombo.currentIndex()]
                title = OT_BOOKS[self.bookCombo.currentIndex()]
            if self.nt.isChecked():
                book = NT_INDEXES[self.bookCombo.currentIndex()]
                title = NT_BOOKS[self.bookCombo.currentIndex()]

            chapter = stringToInt(self.chapterEdit.text())
            beginVerse = stringToInt(self.beginEdit.text())

            if re.match("[0-9]+", self.endEdit.text()):
                endVerse = stringToInt(self.endEdit.text())
                totalVerses = (endVerse - beginVerse) + 1
            else:
                totalVerses = 1
            
            version = self.versionCombo.currentText()
            templatePath = self.templateEdit.text()
            if slideSword(version, templatePath, book, title, chapter, beginVerse, totalVerses):
                self.msb = QMessageBox.information(self, u"訊息", u"操作完成")
            else:
                self.msb = QMessageBox.warning(self, u"訊息", u"產出錯誤，請確認輸入內容正確")
        else:
            self.msb = QMessageBox.information(self, u"訊息", u"無效的輸入格式")

    def generateTxtButtonPushed(self):
        if self.versionCombo.currentText() == "":
            self.msb = QMessageBox.information(self, u"訊息", u"找不到聖經檔, 操作終止")
        elif re.match("[0-9]+", self.chapterEdit.text()) and re.match("[0-9]+", self.beginEdit.text()):
            if self.ot.isChecked():
                book = OT_INDEXES[self.bookCombo.currentIndex()]
                title = OT_BOOKS[self.bookCombo.currentIndex()]
            if self.nt.isChecked():
                book = NT_INDEXES[self.bookCombo.currentIndex()]
                title = NT_BOOKS[self.bookCombo.currentIndex()]

            chapter = stringToInt(self.chapterEdit.text())
            beginVerse = stringToInt(self.beginEdit.text())

            if re.match("[0-9]+", self.endEdit.text()):
                endVerse = stringToInt(self.endEdit.text())
                totalVerses = (endVerse - beginVerse) + 1
            else:
                totalVerses = 1
            
            version = self.versionCombo.currentText()
            templatePath = self.templateEdit.text()
            if txtSword(version, book, title, chapter, beginVerse, totalVerses):
                self.msb = QMessageBox.information(self, u"訊息", u"操作完成")
            else:
                self.msb = QMessageBox.warning(self, u"訊息", u"產出錯誤，請確認輸入內容正確")
        else:
            self.msb = QMessageBox.information(self, u"訊息", u"無效的輸入格式")


    def aboutButtonPushed(self):  
        self.about = Dialog()
        self.about.exec_()
        
    def dragEnterEvent(self, event):
        data = event.mimeData()
        if data.hasUrls():
            event.acceptProposedAction()
        
    def dropEvent(self, event):
        for x in range(0, len(event.mimeData().urls())):
            fn = event.mimeData().urls()[x].toLocalFile()
            if filter(fn.lower().endswith, HTML_EXT):
                self.templateEdit.setText(os.path.abspath(fn))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window1 = MainWindow()
    window1.setWindowTitle(PRODUCT_NAME)
    window1.setFixedSize(DEFAULT_WIDTH, DEFAULT_HEIGHT)
    window1.show()
    app.exec_()
    sys.exit()
