#!/usr/bin/env python
#-*- coding: UTF-8 -*-

__author__ = 'helljump'

import logging
import startup  # @UnusedImport
from utils import MyProgressDialog
from PyQt4 import QtGui
from PyQt4 import QtCore
from dbobj import Document
import re
import codecs
from ZODB.utils import p64
import os
from pytils.translit import slugify
from ZODB.POSException import POSKeyError
from dateutil.parser import parse
import transaction
from datetime import datetime


log = logging.getLogger(__name__)


def parse_xml(data):
    assert isinstance(data, unicode)
    for item in re.finditer(r"(?imsu)<item>(.+?)</item>", data):
        egg = {'text': u''}
        if (not re.search("(?imsu)<wp:post_type>post</wp:post_type>", item.group(1)) and
                not re.search("(?imsu)<wp:post_type>page</wp:post_type>", item.group(1))):
            continue
        m = re.search("(?imsu)<title>(.+?)</title>", item.group(1))
        if m:
            egg["title"] = m.group(1)
        m = re.search("(?imsu)<wp:post_date>(.+?)</wp:post_date>", item.group(1))
        if m:
            egg["date"] = parse(m.group(1))
        m = re.search("(?imsu)<content:encoded><!\[CDATA\[(.+?)\]\]></content:encoded>", item.group(1))
        if m:
            egg["text"] = m.group(1).replace('<!--more-->', '<hr class="more">')
        m = re.search("(?imsu)<excerpt:encoded><!\[CDATA\[(.+?)\]\]></excerpt:encoded>", item.group(1))
        if m and len(m.group(1)) > 3:
            egg['text'] = egg['text'].replace('<hr class="more">', '')
            egg["text"] = "%s\n<hr class='more'>\n%s" % (m.group(1), egg['text'])
        m = re.search("(?imsu)<category.+?><!\[CDATA\[(.+?)\]\]></category>", item.group(1))
        if m:
            egg["category"] = m.group(1)
        else:
            egg["category"] = u'Новости'
        m = re.search("(?imsu)<wp:post_id>(\d+)</wp:post_id>", item.group(1))
        if m:
            egg["post_id"] = m.group(1)
        m = re.search("(?imsu)<wp:post_parent>(\d+)</wp:post_parent>", item.group(1))
        if m:
            egg["post_parent"] = m.group(1)
        m = re.findall("(?imsu)<category domain=\"(post_tag|tag)\".+?><!\[CDATA\[(.+?)\]\]></category>", item.group(1))
        if m:
            egg["tags"] = [row[1] for row in m]
        else:
            egg["tags"] = []
        yield(egg)


def reader(parent):
    fn = QtGui.QFileDialog.getOpenFileName(parent, u'Импорт', QtCore.QString(), u'Wordpress XML (*.xml)')
    if fn.isEmpty():
        return False
    fn = unicode(fn)
    pdlg = MyProgressDialog(u'Импорт', u'Чтение файла', u'Отмена', parent=parent)
    pdlg.show()
    root = parent.project.root()
    documents = root["documents"]
    cats = root["cats"]
    tags = root["tags"]
    docs = 0
    try:
        data = codecs.open(fn, 'r', 'utf-8').read()
        for d in parse_xml(data):
            doc = Document()
            doc.title = d['title']
            doc.text = d['text']
            doc.date = d['date']
            doc.tags = set(d['tags'])
            doc.cats = set([d['category']])
            docs += 1
            documents.appendSorted(doc)
            cats.update(doc.cats)
            tags.update(doc.tags)
            if docs % 100 == 0:
                QtGui.qApp.processEvents()
            if pdlg.wasCanceled():
                raise IOError('Canceled')
        transaction.commit()
        log.debug('docs %i', docs)
    except:
        transaction.abort()
        raise
    finally:
        pdlg.close()
    return True


HEADER = """<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0"
    xmlns:excerpt="http://wordpress.org/export/1.2/excerpt/"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:wp="http://wordpress.org/export/1.2/"
>
<channel>
    <title>%s</title>
    <link>http://wp.localhost</link>
    <description>Just another WordPress site</description>
    <pubDate>%s</pubDate>
    <language>ru-RU</language>
    <wp:wxr_version>1.2</wp:wxr_version>
    <wp:base_site_url>http://localhost</wp:base_site_url>
    <wp:base_blog_url>http://localhost</wp:base_blog_url>
    <wp:author><wp:author_id>1</wp:author_id><wp:author_login>admin</wp:author_login><wp:author_email>ad@min.ru</wp:author_email><wp:author_display_name><![CDATA[admin]]></wp:author_display_name><wp:author_first_name><![CDATA[]]></wp:author_first_name><wp:author_last_name><![CDATA[]]></wp:author_last_name></wp:author>
    <generator>http://zipta.ru</generator>
"""

FOOTER = """</channel>
</rss>
"""

CAT = """    <wp:category><wp:term_id>%(id)i</wp:term_id><wp:category_nicename>%(slug)s</wp:category_nicename><wp:category_parent></wp:category_parent><wp:cat_name><![CDATA[%(text)s]]></wp:cat_name></wp:category>
"""

TAG = """    <wp:tag><wp:term_id>%(id)i</wp:term_id><wp:tag_slug>%(slug)s</wp:tag_slug><wp:tag_name><![CDATA[%(text)s]]></wp:tag_name></wp:tag>
"""

ITEM = """
    <item>
        <title>%(title)s</title>
        <link>http://localhost/?p=%(id)i</link>
        <pubDate>%(pubdate)s</pubDate>
        <dc:creator><![CDATA[admin]]></dc:creator>
        <guid isPermaLink="false">http://localhost/?p=%(id)i</guid>
        <description></description>
        <content:encoded><![CDATA[%(text)s]]></content:encoded>
        <excerpt:encoded><![CDATA[]]></excerpt:encoded>
        <wp:post_id>%(id)i</wp:post_id>
        <wp:post_date>%(date)s</wp:post_date>
        <wp:post_date_gmt>%(date)s</wp:post_date_gmt>
        <wp:comment_status>open</wp:comment_status>
        <wp:ping_status>open</wp:ping_status>
        <wp:post_name>%(slug)s</wp:post_name>
        <wp:status>publish</wp:status>
        <wp:post_parent>0</wp:post_parent>
        <wp:menu_order>0</wp:menu_order>
        <wp:post_type>post</wp:post_type>
        <wp:post_password></wp:post_password>
        <wp:is_sticky>0</wp:is_sticky>"""

ITEMCAT = """
        <category domain="category" nicename="%(slug)s"><![CDATA[%(text)s]]></category>"""

ITEMTAG = """
        <category domain="post_tag" nicename="%(slug)s"><![CDATA[%(text)s]]></category>"""

ITEMFOOT = """
    </item>
"""


def write_xml(prj, fn):
    img_re = re.compile('(cm3\://image/(\d+))')
    prefs = prj.root().get('prefs', {})
    conn = prj.con()
    ww = prefs.get('image_width', 200)
    hh = prefs.get('image_height', 200)
    imgdir = prefs.get('image_dir', 'images')
    documents = prj.root()['documents']
    docs = sorted(documents, key=lambda doc: str(doc.cats))
    if re.match("^[a-z]\:", imgdir, re.IGNORECASE) is None:  # rel path
        imgdir = os.path.join(os.path.dirname(fn), imgdir)
    if not os.path.isdir(imgdir):
        os.makedirs(imgdir)
    fout = codecs.open(fn, 'w', 'utf-8')
    egg = datetime.now().strftime("%a, %d %b %Y %H:%M:%S +0000")  # Wed, 19 Mar 2014 11:08:52 +0000
    fout.write(HEADER % (prj.title, egg))
    for i, item in enumerate(prj.root()['cats']):
        fout.write(CAT % {'id': i, 'text': item, 'slug': slugify(item)})
    for i, item in enumerate(prj.root()['tags'], len(prj.root()['cats'])):
        fout.write(TAG % {'id': i, 'text': item, 'slug': slugify(item)})

    for j, doc in enumerate(docs):
        text = doc.text.replace("<hr class='more'>", '<!--more-->')
        #image patch
        for i, row in enumerate(img_re.findall(text)):
            url, oid = row
            try:
                obj = conn.get(p64(int(oid)))
                data = obj.data.open('r').read()
                if data[1:4] == 'PNG':
                    format = 'PNG'
                else:
                    format = 'JPG'
                img = QtGui.QImage.fromData(data)
                if img.width() > ww or img.height() > hh:
                    img = img.scaled(ww, hh, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
                if i > 0:
                    imgname = "%s-%i.%s" % (doc.get_slug(), i, format.lower())
                else:
                    imgname = "%s.%s" % (doc.get_slug(), format.lower())
                egg = "%s/%s" % (imgdir, imgname)
                img.save(egg, format)
                text = text.replace(url, egg)
            except POSKeyError:
                log.error('wrong link %s', url)
        fout.write(ITEM % {
            'id': j,
            'title': doc.title,
            'pubdate': doc.date.strftime("%a, %d %b %Y %H:%M:%S +0000"),
            'date': doc.date.strftime("%Y-%m-%d %H:%M:%S"),
            'text': text,
            'slug': slugify(doc.title)
            })
        for item in doc.cats:
            fout.write(ITEMCAT % {'slug': slugify(item), 'text': item})
        for item in doc.tags:
            fout.write(ITEMTAG % {'slug': slugify(item), 'text': item})
        fout.write(ITEMFOOT)
        yield j
    fout.write(FOOTER)
    fout.close()


def writer(parent):
    fn = QtGui.QFileDialog.getSaveFileName(parent, u'Экспорт', QtCore.QString(), u'Wordpress XML (*.xml)')
    if fn.isEmpty():
        return False
    fn = unicode(fn)
    prj = parent.project
    documents = prj.root()['documents']
    pdlg = MyProgressDialog(u'Экспорт', u'Открытие файла', u'Отмена', 0, len(documents), parent=parent)
    pdlg.show()
    QtGui.qApp.processEvents()
    try:
        for j in write_xml(prj, fn):
            pdlg.set_text(u'Запись')
            pdlg.setValue(j)
            if j % 100 == 0:
                QtGui.qApp.processEvents()
            if pdlg.wasCanceled():
                raise IOError('Canceled')
        log.debug('done')
    finally:
        pdlg.close()


if __name__ == '__main__':
    for d in parse_xml(codecs.open(r'd:\work2014\cm3\_test\1.xml', 'r', 'utf-8').read()):
        print d['tags'],

    #root = startup.CONN.root()
    #prj = root["projects"][0]
    #prj.open()
    #for j in write_xml(prj, r'd:\work2014\cm3\_test\1.xml'):
    #    print j,
    #prj.close()
