# -*- coding: utf-8 -*-

import os
import sys
import xmlrpclib

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

from trac.core import *
from trac.wiki.model import WikiPage
from trac.attachment import Attachment
from trac.util.html import Markup
from trac.mimeview.api import Context
from trac.resource import *
from trac.wiki.formatter import WikiParser

from tracrpc.api import IXMLRPCHandler

from xhtmltowiki import XhtmlToWikiFormatter
from wikitohtml import wiki_to_html,WikiToEditHtmlFormatter

class BlogWikiCore(Component):
    username = ''

    def _getTempPage(self,username,realm='wiki'):
        return  'tempolaryOf' + username

    def _get_categories(self,req,pagename,realm='wiki'):
        result = []
        dic = dict(description='aa',title='ti')
        result.append(dic)
        return result

    def _get_page(self, req, pagename,username,realm='wiki'):
        page = WikiPage(self.env, pagename, version=None)
        if page.exists:
            resource = Resource('wiki',pagename)
            context = Context(Resource('wiki',pagename))
            context.req = req
            #out = StringIO()
            #WikiToEditHtmlFormatter(self.env, context).format( WikiParser(self.env).parse(page.text), out,
            #                                         escape_newlines=False)
            #html= '<html><body>%s</body></html>' % out.getvalue()
            
            #html = '<html><body>%s</body></html>' % HtmlFormatter(self.env, context, page.text).generate(escape_newlines=False)
            html = '<html><body>%s</body></html>' % wiki_to_html(page.text, self.env, req, absurls=1,resource=resource)
            return page,html
            dic = dict(postid=pagename,
                       dateCreated=xmlrpclib.DateTime(page.time),
                       title=page.name,
                       description=html,
                       categories=[],#self._get_categories(req,page.name),
                       link='',
                       publish=True)
            return dic
        else:
            msg = 'Wiki page "%s" does not exist' % pagename
            if version is not None:
                msg += ' at version %s' % version
            raise xmlrpclib.Fault(0, msg)

    def _put_page(self, req, pagename, content, username):
        self.username = username
        """ writes the content of the page. """
        page = WikiPage(self.env, pagename)
        if page.readonly:
            req.perm.assert_permission('WIKI_ADMIN')
        elif not page.exists:
            req.perm.assert_permission('WIKI_CREATE')
        else:
            req.perm.assert_permission('WIKI_MODIFY')

        ctx = Context.from_request(req,'wiki', pagename,absurls=True)

        self.log.debug(content['description'])
        hoge = XhtmlToWikiFormatter(self.env,ctx)
        hoge.setReq(req)
        hoge.setCaller(self)

        hoge.setTempPage(self._getTempPage(username))
        text = hoge.xhtmltowiki(content['description'])
        self.log.debug(text)
        page.text = text
        page.save(username,
                  None,
                  req.remote_addr)
        self._move_temp_attachment(pagename,username)
        #delete temp page
        self._delete_temp_page(username)
        return True
    
    def _delete_temp_page(self,username):
        db = self.env.get_db_cnx()
        page = WikiPage(self.env, self._getTempPage(username))
        if page.exists:
            page.delete(db=db)

        db.commit()
    
    def _move_temp_attachment(self,pagename,username):
        db = self.env.get_db_cnx()
        temp_attachments = Attachment.select(self.env, 'wiki', self._getTempPage(self.username),db=db)
        for temp_att in temp_attachments:
            filename = temp_att.filename
            try:
                data = temp_att.open().read()
                new_att = Attachment(self.env, 'wiki', pagename)
                new_att.author = username or 'anonymous'
                new_att.description = temp_att.description
                new_att.insert(filename, StringIO(data), len(data),db=db)
            except ResourceNotFound:
                self.log.error('ResourceNotFound: Attachment %s not found'%filename)
                pass
        Attachment.delete_all(self.env, 'wiki', self._getTempPage(self.username),db=db)
        db.commit()

    def _put_attachment(self, req, pagename,username,password,file,realm='wiki'):
        page = WikiPage(self.env, pagename)
        filename = file['name'].split('/')[-1]
        data = file['bits']
        if not page.exists:
            pagename=self._getTempPage(username)
            page = WikiPage(self.env, pagename)
            if not page.exists:
                page.text = 'dumy'
                page.save(username,
                          None,
                          req.remote_addr)
        try:
            attachment = Attachment(self.env, 'wiki', pagename, filename)
            attachment.delete()
        except TracError:
            pass
        attachment = Attachment(self.env, 'wiki', pagename)
        attachment.author = req.authname or 'anonymous'
        attachment.description = None
        attachment.insert(filename, StringIO(data.data), len(data.data))
        filename = attachment.filename

        href = req.abs_href('raw-attachment','wiki', pagename, filename)
        #self.log.debug (href)
        return href

    def _get_page_list(self, req, username,numberOfPosts=-1,orderby=''):
        """ Get list of changed pages since timestamp """
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        limit=''
        if orderby != '':
            orderby = " ORDER BY %s "%orderby
            self.log.debug('orderby:%s'%orderby)
        if numberOfPosts != -1:
            limit = " Limit %s "%numberOfPosts
            
        cursor.execute('SELECT name, max(time), author, version, comment FROM wiki'
                       '  GROUP BY name ' + orderby + limit )
        result = []
        rowid = 0
        cate = []
        #cate.append(dict(discription='hoge',title='wiki'))
        for name, time, author, version, comment in cursor:
            rowid = rowid+1
            if rowid <= numberOfPosts: 
                dic = dict(postid=name,
                           dateCreated=xmlrpclib.DateTime(int(time)),
                           title=name,
                           description='',
                           categories=self._get_categories(req,name),
                           publish=True)
                result.append(dic)
        return result
    
    #Callback method from XhtmlToWikiFormatter
    def attachmentUrl(self,url,ctx):
        pagename = ctx.id
        filename = url.split('/')[-1]
        #checkctx = Context(ctx.env, ctx.req)
        
        checkctx = ctx('raw-attachment','wiki')(abs_urls=True)
        # attachment in this page 
        checkctx1url = checkctx.resource_href(pagename+'/'+filename)
        if url == checkctx1url:
            self.log.debug("%s -> %s"%(url,filename))
            return filename        
        # attachment in temp page 
        checkctx2url = checkctx.resource_href(self._getTempPage(self.username)+'/'+filename)
        if url == checkctx2url:
            self.log.debug("%s -> %s"%(url,filename))
            return filename
        return url

class MetaweblogAPIToWikiRPC(BlogWikiCore):
    implements(IXMLRPCHandler)

#    def __init__(self):
#        self.wiki = WikiSystem(self.env)

    def xmlrpc_namespace(self):
        return 'metaWeblog'

    def xmlrpc_methods(self):
        yield ('WIKI_VIEW', ((dict,str, str, str,  int),), self.getRecentPosts)
        yield ('WIKI_CREATE', ((str, str, str, str, dict, bool),), self.newPost)
        yield ('WIKI_MODIFY', ((str, str, str, str, dict, bool),), self.editPost)
        yield ('WIKI_VIEW', ((str, str, str, str),), self.getPost)
        #yield ('WIKI_DELETE', ((str, str, str, str, bool),), self.deletePost)
        yield ('WIKI_MODIFY', ((str, str, str, str, dict),), self.newMediaObject )
        yield ('WIKI_VIEW', ((dict,str, str, str),), self.getCategories )

    def getCategories(self, req, blogid,username,password):
        self.log.debug( 'metaWeblog.getCategories(%s,%s,%s)' %( blogid,username,password))
        return self._get_categories(req,blogid)


    def newMediaObject(self, req, blogid,username,password,file):
        self.log.debug('metaWeblog.newMediaObject(%s,%s,%s,%s)' %( blogid,username,password,file))
        return dict(url=self._put_attachment(req, str(blogid), username, password, file))

    def getPost(self, req, blogid,username,password):
        self.log.debug('metaWeblog.getPost(%s,%s,%s)' %( blogid,username,password))
        page,html = self._get_page( req, blogid,username)
        dic = dict(postid=page.name,
                   dateCreated=xmlrpclib.DateTime(page.time),
                   title=page.name,
                   description=html,
                   categories=[],#self._get_categories(req,page.name),
                   link='',
                   publish=True)
        return dic

    def newPost(self, req, blogid,username,password,content,publish):
        self.log.debug('metaWeblog.newPost(%s,%s,%s,%s,%s)' %( blogid,username,password,content,publish))
        self._put_page(req,content['title'],content,username)
        return content['title']

    def editPost(self, req, postid,username,password,content,publish):
        self.log.debug('metaWeblog.editPost(%s,%s,%s,%s,%s)' %( postid,username,password,content,publish))
        self._put_page(req,postid,content,username)
        return postid

    # note used
    #def deletePost(self, req, blogid,username,password,publish):
    #    self.log.debug('metaWeblog.deletePost(%s,%s,%s,%s)' %( blogid,username,password,publish))
    #    return blogid

    def getRecentPosts(self, req, blogid,username,password,numberOfPosts):
        self.log.debug('metaWeblog.getRecentPosts(%s,%s,%s,%s)' %( blogid,username,password,numberOfPosts))
        return self._get_page_list( req, username,numberOfPosts,"max(time) DESC")

class WordPressAPIToWikiRPC(MetaweblogAPIToWikiRPC):    #hirobe
    """Superset of the
    [http://www.jspwiki.org/Wiki.jsp?page=WikiRPCInterface2 WikiRPC API]. """

    implements(IXMLRPCHandler)


#    def __init__(self):
#        self.wiki = WikiSystem(self.env)

    def xmlrpc_namespace(self):
        return 'wp'    #hirobe

    def xmlrpc_methods(self):
        yield ('WIKI_VIEW', ((dict,str, str, str),), self.getCategories )
        yield ('WIKI_VIEW', ((dict,str, str, str,int),), self.getPages )
        yield ('WIKI_VIEW', ((dict,str, str, str, str),), self.getPage )
        yield ('WIKI_MODIFY', ((dict,str, str,str, str, str),), self.editPage )

    def getCategories(self, req, blogid,username,password):
        self.log.debug( 'wp.getCategories(%s,%s,%s)' %( blogid,username,password))
        #print>>sys.stderr, blogid
        return self._get_categories(req,blogid)

    def getPages(self, req, blogid,username,password,numberOfPosts):
        self.log.debug( 'wp.getPages(%s,%s,%s,%s)' %( blogid,username,password,numberOfPosts))
        #print>>sys.stderr, blogid
        return self._get_page_list( req, username,numberOfPosts,orderby="name")

    def getPage(self, req, blogid,pageid, username,password):
        self.log.debug( 'wp.getPages(%s,%s,%s,%s)' %( blogid,pageid,username,password))
        page,html = self._get_page( req, pageid,username)
        dic = dict(postid=page.name,
                   dateCreated=xmlrpclib.DateTime(page.time),
                   title=page.name,
                   description=html,
                   categories=[],#self._get_categories(req,page.name),
                   link='',
                   publish=True)
        return dic
    
    def editPage(self, req, blogid,username,password,pageid,content,publish):
        self.log.debug('wp.editPost(%s,%s,%s,%s,%s,%s)' %( blogid,username,password,pageid,content,publish))
        self._put_page(req,pageid,content,username)
        return pageid


class BloggerAPIToWikiRPC(BlogWikiCore):
    implements(IXMLRPCHandler)


#    def __init__(self):
#        self.wiki = WikiSystem(self.env)

    def xmlrpc_namespace(self):
        return 'blogger'    #hirobe

    def xmlrpc_methods(self):
        yield ('WIKI_VIEW', ((dict,str, str, str),), self.getUsersBlogs)
        yield ('WIKI_VIEW', ((dict,str, str, str, str, int),), self.getRecentPosts)
        yield ('WIKI_DELETE', ((bool , str, str, str,str, bool),), self.deletePost)

        #yield ('WIKI_VIEW', ((dict,str, str, str),), self.getUserInfo)
        #yield ('WIKI_VIEW', ((dict,str, str, str, str),), self.getPost)
        #yield ('WIKI_CREATE', ((str, str, str, str, str, str, bool),), self.newPost)
        #yield ('WIKI_MODIFY', ((str, str, str, str, str, str, bool),), self.editPost)

    def getUsersBlogs(self, req, appkey,username,password):
        self.log.debug('blogger.getUsersBlogs(%s,%s,%s)' %( appkey,username,password))

        # as word 2007 bug blogid must be int.
        #　live wirter use this url to search design 
        dic = dict(url=req.abs_href('wlwriter'),blogid='9999',
                   blogName='wiki')
        result = []
        result.append(dic)
        return result

    def getRecentPosts(self, req, appkey,blogid,username,password,numberOfPosts):
    #def getRecentChanges(self, req, since):
        self.log.debug('blogger.getRecentPosts(%s,%s,%s,%s,%s)' %( appkey,blogid,username,password,numberOfPosts))
        """ Get list of changed pages since timestamp """
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute('SELECT name, max(time), author, version, comment FROM wiki'
                       '  GROUP BY name ORDER BY max(time) DESC')
        result = []
        rownum = 0
        for name, time, author, version, comment in cursor:
            rownum +=1
            if rownum <= numberOfPosts:
                #result.append(self._page_info(name, time, author, version, comment))
                dic = dict(dateCreated=xmlrpclib.DateTime(int(time)),userid=author,
                           postid=name,content='')
                           
                result.append(dic)
        return result

    def deletePage(self, req, name, version=None):
        page = WikiPage(self.env, name, version)
        page.delete(version)
        return True

    def getPost(self, req,appkey, blogid,username,password):
        self.log.debug('blogger.getPost(%s,%s,%s)' %( blogid,username,password))
        return 'hoge'

    def getUserInfo(self, req, blogid,username,password):
        self.log.debug('blogger.getUserInfo(%s,%s,%s)' %( blogid,username,password))
        return 'hoge'

    def newPost(self, req, appkey, blogid,username,password,content,publish):
        self.log.debug('blogger.newPost(%s,%s,%s,%s,%s)' %( blogid,username,password,content,publish))
        return blogid

    def editPost(self, req, appkey, blogid,username,password,content,publish):
        self.log.debug('blogger.editPost(%s,%s,%s,%s,%s)' %( blogid,username,password,content,publish))
        return blogid

    def deletePost(self, req,appkey, blogid,username,password,publish):
        self.log.debug('blogger.deletePost(%s,%s,%s,%s)' %( blogid,username,password,publish))
        db = self.env.get_db_cnx()
        page = WikiPage(self.env, blogid)
        exi = page.exists
        if page.exists:
            page.delete(db=db)
        db.commit()

        if blogid == self._getTempPage(username):
            return True
        else:
            return exi



