from time import sleep
from datetime import datetime

from pylons import g #g is a namespace for globally accessable app helpers
from pylons import c as context
import re

from pymongo.errors import OperationFailure

from ming import schema
from ming.orm.base import state, session
from ming.orm.mapped_class import MappedClass
from ming.orm.property import FieldProperty

from allura.model import VersionedArtifact, Snapshot, Message

wikiwords = [
    (r'\b([A-Z]\w+[A-Z]+\w+)', r'<a href="../\1/">\1</a>'),
    ]

wikiwords = [
    (re.compile(pattern), replacement)
    for pattern, replacement in wikiwords ]

def to_html(text):
    content = g.markdown.convert(text)
    for pattern, replacement in wikiwords:
        content = pattern.sub(replacement, content)
    return content

class PageHistory(Snapshot):
    class __mongometa__:
        name='hello_page_history'

    def original(self):
        return Page.query.get(_id=self.artifact_id)
        
    def url(self):
        return self.original().url() + '?version=%d' % self.version

    def index(self):
        result = Snapshot.index(self)
        result.update(
            title_s='Version %d of %s' % (
                self.version,self.original().title),
            type_s='WikiPage Snapshot',
            text=self.data.text)
        return result

    @property
    def html_text(self):
        """A markdown processed version of the page text"""
        return to_html(self.data.text)

    def root_comments(self):
        if '_id' in self:
            return Comment.query.find(dict(page_id=self.artifact_id, parent_id=None))
        else:
            return []

class Page(VersionedArtifact):
    class __mongometa__:
        name='hello_page'
        history_class = PageHistory

    title=FieldProperty(str)
    text=FieldProperty(schema.String, if_missing='')

    def url(self):
        return self.app_config.url() + self.title + '/'

    def shorthand_id(self):
        return self.title

    def index(self):
        result = VersionedArtifact.index(self)
        result.update(
            title_s='HelloForge WikiPage %s' % self.title,
            version_i=self.version,
            type_s='WikiPage',
            text=self.text)
        return result
    
    @classmethod
    def upsert(cls, title, version=None):
        """Update page with `title` or insert new page with that name"""
        
        #If no version is specified
        if version is None:
            #Check for existing page object    
            obj = cls.query.get(
                app_config_id=context.app.config._id,
                title=title)
                
            #If there's no page, make one
            if obj is None:
                obj = cls(
                    title=title,
                    app_config_id=context.app.config._id,
                    )
            return obj
        else:
            #version was specified, move up from there and save...
            pg = cls.upsert(title)
            HC = cls.__mongometa__.history_class
            ss = HC.query.find({'artifact_id':pg._id, 'version':int(version)}).one()
            return ss

    @property
    def html_text(self):
        """A markdown processed version of the page text"""
        return to_html(self.text)

    def reply(self):
        while True:
            try:
                c = Comment(page_id=self._id)
                return c
            except OperationFailure:
                sleep(0.1)
                continue

    def root_comments(self):
        if '_id' in self:
            return Comment.query.find(dict(page_id=self._id, parent_id=None))
        else:
            return []

class Comment(Message):
    """Comment class, threaded, persisted in mongo on a per-page basis"""
    
    class __mongometa__:
        name='hello_comment'
    page_id=FieldProperty(schema.ObjectId)

    def index(self):
        result = Message.index(self)
        author = self.author()
        result.update(
            title_s='Comment on page %s by %s' % (
                self.page.title, author.display_name),
            type_s='Comment on WikiPage',
            page_title_t=self.page.title)
        return result

    @property
    def page(self):
        """The page this comment connects too"""
        return Page.query.get(_id=self.page_id)

    @property
    def posted_ago(self):
        comment_td = (datetime.utcnow() - self.timestamp)
        if comment_td.seconds < 3600 and comment_td.days < 1:
            return "%s minutes ago" % (comment_td.seconds / 60)
        elif comment_td.seconds >= 3600 and comment_td.days < 1:
            return "%s hours ago" % (comment_td.seconds / 3600)
        elif comment_td.days >= 1 and comment_td.days < 7:
            return "%s days ago" % comment_td.days
        elif comment_td.days >= 7 and comment_td.days < 30:
            return "%s weeks ago" % (comment_td.days / 7)
        elif comment_td.days >= 30 and comment_td.days < 365:
            return "%s months ago" % (comment_td.days / 30)
        else:
            return "%s years ago" % (comment_td.days / 365)

    def url(self):
        """The URL for this specific comment"""
        return self.page.url() + '#comment-' + self._id

    def shorthand_id(self):
        return '%s-%s' % (self.page.title, self._id)

MappedClass.compile_all()
