#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

#-*- python -*-
import logging
import urllib2
import json

# Non-stdlib imports
import pymongo
from tg import config, expose, validate, redirect, flash, jsonify
from tg.decorators import with_trailing_slash, without_trailing_slash
from pylons import tmpl_context as c
from pylons import app_globals as g
from pylons import request
from paste.deploy.converters import asbool
import formencode
from formencode import validators
from webob import exc

from ming.orm import session

# Allura-specific imports
from allura.app import Application, SitemapEntry, ConfigOption
from allura.app import DefaultAdminController
from allura.lib import helpers as h
from allura.lib.utils import JSONForExport
from allura.lib.search import search_app
from allura.lib.decorators import require_post, memorable_forget
from allura.lib.security import has_access, require_access
from allura.lib import widgets as w
from allura.lib import exceptions as forge_exc
from allura.lib.widgets.subscriptions import SubscribeForm
from allura.lib.widgets import form_fields as ffw
from allura.lib.widgets.search import SearchResults, SearchHelp
from allura import model as M
from allura.controllers import BaseController, AppDiscussionController, AppDiscussionRestController
from allura.controllers.attachments import AttachmentController, AttachmentsController
from allura.controllers.rest import AppRestControllerMixin
from allura.controllers.feed import FeedArgs, FeedController

# Local imports
from forgeblog import model as BM
from forgeblog import version
from forgeblog import widgets

log = logging.getLogger(__name__)


class W:
    thread = w.Thread(
        page=None, limit=None, page_size=None, count=None,
        style='linear')
    pager = widgets.BlogPager()
    new_post_form = widgets.NewPostForm()
    edit_post_form = widgets.EditPostForm()
    view_post_form = widgets.ViewPostForm()
    attachment_list = ffw.AttachmentList()
    confirmation = ffw.Lightbox(name='confirm',
                            trigger='a.post-link',
                            options="{ modalCSS: { minHeight: 0, width: 'inherit', top: '150px'}}")
    preview_post_form = widgets.PreviewPostForm()
    subscribe_form = SubscribeForm(thing='post')
    search_results = SearchResults()
    help_modal = SearchHelp(fields={'title': 'Title',
                                    'text': '"Post text"',
                                    'labels_t': 'Labels',
                                    'mod_date_dt': 'Last modified.  Example: mod_date_dt:[2018-01-01T00:00:00Z TO *]',
                                    'author_user_name_t': 'username (for comments only)',
                                    })


class ForgeBlogApp(Application):
    __version__ = version.__version__
    tool_label = 'Blog'
    tool_description = """
        Share exciting news and progress updates with your
        community.
    """
    default_mount_label = 'Blog'
    default_mount_point = 'blog'
    permissions = ['configure', 'read', 'write',
                   'unmoderated_post', 'post', 'moderate', 'admin']
    permissions_desc = {
        'read': 'View blog entries.',
        'write': 'Create new blog entry.',
        'admin': 'Set permissions. Enable/disable commenting.',
    }
    config_options = Application.config_options + [
        ConfigOption('AllowEmailPosting', bool, True)
    ]
    ordinal = 14
    exportable = True
    searchable = True
    config_options = Application.config_options
    default_external_feeds = []
    icons = {
        24: 'images/blog_24.png',
        32: 'images/blog_32.png',
        48: 'images/blog_48.png'
    }

    def __init__(self, project, config):
        Application.__init__(self, project, config)
        self.root = RootController()
        self.admin = BlogAdminController(self)
        self.api_root = RootRestController()

    @property
    def external_feeds_list(self):
        globals = BM.Globals.query.get(app_config_id=self.config._id)
        if globals is not None:
            external_feeds = globals.external_feeds
        else:
            external_feeds = self.default_external_feeds
        return external_feeds

    @external_feeds_list.setter
    def external_feeds_list(self, new_external_feeds):
        globals = BM.Globals.query.get(app_config_id=self.config._id)
        if globals is not None:
            globals.external_feeds = new_external_feeds
        elif len(new_external_feeds) > 0:
            globals = BM.Globals(
                app_config_id=self.config._id, external_feeds=new_external_feeds)
        if globals is not None:
            session(globals).flush()

    def main_menu(self):
        return [SitemapEntry(self.config.options.mount_label, '.')]

    @property
    @h.exceptionless([], log)
    def sitemap(self):
        menu_id = self.config.options.mount_label
        with h.push_config(c, app=self):
            return [
                SitemapEntry(menu_id, '.')[self.sidebar_menu()]]

    @property
    def show_discussion(self):
        if 'show_discussion' in self.config.options:
            return self.config.options['show_discussion']
        else:
            return True

    @property
    def allow_email_posting(self):
        return self.config.options.get('AllowEmailPosting', True)

    @allow_email_posting.setter
    def allow_email_posting(self, show):
        self.config.options['AllowEmailPosting'] = bool(show)

    @h.exceptionless([], log)
    def sidebar_menu(self):
        base = c.app.url
        links = [
            SitemapEntry('Home', base),
        ]
        if has_access(self, 'write')():
            links += [SitemapEntry('New Post', base + 'new')]
        return links

    def admin_menu(self):
        admin_url = c.project.url() + 'admin/' + \
            self.config.options.mount_point + '/'
        # temporarily disabled until some bugs are fixed
        links = super(ForgeBlogApp, self).admin_menu(force_options=True)
        # We don't want external feeds in menu unless they're enabled
        if asbool(config.get('forgeblog.exfeed', 'false')):
            links.insert(0, SitemapEntry('External feeds',
                         admin_url + 'exfeed', className='admin_modal'))
        return links
        # return super(ForgeBlogApp, self).admin_menu(force_options=True)

    def install(self, project):
        'Set up any default permissions and roles here'
        super(ForgeBlogApp, self).install(project)

        # Setup permissions
        role_admin = M.ProjectRole.by_name('Admin')._id
        role_developer = M.ProjectRole.by_name('Developer')._id
        role_auth = M.ProjectRole.by_name('*authenticated')._id
        role_anon = M.ProjectRole.by_name('*anonymous')._id
        self.config.acl = [
            M.ACE.allow(role_anon, 'read'),
            M.ACE.allow(role_auth, 'post'),
            M.ACE.allow(role_auth, 'unmoderated_post'),
            M.ACE.allow(role_developer, 'write'),
            M.ACE.allow(role_developer, 'moderate'),
            M.ACE.allow(role_admin, 'configure'),
            M.ACE.allow(role_admin, 'admin'),
        ]

    def uninstall(self, project):
        "Remove all the tool's artifacts from the database"
        BM.BlogAttachment.query.remove(dict(app_config_id=c.app.config._id))
        BM.BlogPost.query.remove(dict(app_config_id=c.app.config._id))
        BM.BlogPostSnapshot.query.remove(dict(app_config_id=c.app.config._id))
        super(ForgeBlogApp, self).uninstall(project)

    def bulk_export(self, f, export_path='', with_attachments=False):
        f.write('{"posts": [')
        posts = list(BM.BlogPost.query.find(dict(app_config_id=self.config._id)))
        if with_attachments:
            GenericJSON = JSONForExport
            self.export_attachments(posts, export_path)
        else:
            GenericJSON = jsonify.GenericJSON
        for i, post in enumerate(posts):
            if i > 0:
                f.write(',')
            json.dump(post, f, cls=GenericJSON, indent=2)
        f.write(']}')

    def export_attachments(self, articles, export_path):
        for article in articles:
            for post in article.discussion_thread.query_posts(status='ok'):
                post_path = self.get_attachment_export_path(
                    export_path,
                    str(article._id),
                    article.discussion_thread._id,
                    post.slug
                )
                self.save_attachments(post_path, post.attachments)


class RootController(BaseController, FeedController):

    def __init__(self):
        self._discuss = AppDiscussionController()

    def _check_security(self):
        require_access(c.app, 'read')

    @expose('jinja:forgeblog:templates/blog/index.html')
    @with_trailing_slash
    @validate(dict(page=validators.Int(if_empty=0, if_invalid=0),
                   limit=validators.Int(if_empty=None, if_invalid=None)))
    def index(self, page=0, limit=None, **kw):
        query_filter = dict(app_config_id=c.app.config._id)
        if not has_access(c.app, 'write')():
            query_filter['state'] = 'published'
        q = BM.BlogPost.query.find(query_filter)
        post_count = q.count()
        limit, page, _ = g.handle_paging(limit, page)
        limit, page = h.paging_sanitizer(limit, page, post_count)
        posts = q.sort('timestamp', pymongo.DESCENDING) \
                 .skip(page * limit).limit(limit)
        c.form = W.preview_post_form
        c.pager = W.pager
        return dict(posts=posts, page=page, limit=limit, count=post_count)

    @with_trailing_slash
    @expose('jinja:forgeblog:templates/blog/search.html')
    @validate(dict(q=validators.UnicodeString(if_empty=None),
                   history=validators.StringBool(if_empty=False),
                   search_comments=validators.StringBool(if_empty=False),
                   project=validators.StringBool(if_empty=False)))
    def search(self, q=None, history=None, search_comments=None, project=None, limit=None, page=0, **kw):
        c.search_results = W.search_results
        c.help_modal = W.help_modal
        search_params = kw
        search_params.update({
            'q': q or '',
            'history': history,
            'search_comments': search_comments,
            'project': project,
            'limit': limit,
            'page': page,
            'allowed_types': ['Blog Post', 'Blog Post Snapshot'],
            'fq': ['state_s:published']
        })
        return search_app(**search_params)

    @expose('jinja:forgeblog:templates/blog/edit_post.html')
    @without_trailing_slash
    def new(self, **kw):
        require_access(c.app, 'write')
        self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
        post = dict(
            state='published')
        c.form = W.new_post_form
        return dict(post=post)

    @memorable_forget()
    @expose()
    @require_post()
    @validate(form=W.edit_post_form, error_handler=new)
    @without_trailing_slash
    def save(self, **kw):
        require_access(c.app, 'write')
        self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
        attachment = kw.pop('attachment', None)
        post = BM.BlogPost.new(**kw)
        g.spam_checker.check(kw['title'] + u'\n' + kw['text'], artifact=post,
                             user=c.user, content_type='blog-post')
        if attachment is not None:
            post.add_multiple_attachments(attachment)
        redirect(h.really_unicode(post.url()).encode('utf-8'))

    @with_trailing_slash
    @expose('jinja:allura:templates/markdown_syntax_dialog.html')
    def markdown_syntax_dialog(self, **kw):
        'Static dialog page about how to use markdown.'
        return dict()

    @expose()
    def _lookup(self, year=None, month=None, name=None, *rest):
        if year is None or month is None or name is None:
            raise exc.HTTPNotFound()
        slug = '/'.join((year, month, urllib2.unquote(name).decode('utf-8')))
        post = BM.BlogPost.query.get(slug=slug, app_config_id=c.app.config._id)
        if post is None:
            raise exc.HTTPNotFound()
        return PostController(post), rest

    def get_feed(self, project, app, user):
        """
        Return a :class:`allura.controllers.feed.FeedArgs` object describing the xml feed for this controller.
        Overrides :meth:`allura.controllers.feed.FeedController.get_feed`.
        """
        return FeedArgs(
            dict(project_id=project._id, app_config_id=app.config._id,
                 link=BM.BlogPost.link_regex
                 ),
            'Recent posts to %s' % app.config.options.mount_point,
            app.url)


class BlogAttachmentController(AttachmentController):
    AttachmentClass = BM.BlogAttachment


class BlogAttachmentsController(AttachmentsController):
    AttachmentControllerClass = BlogAttachmentController


class PostController(BaseController, FeedController):

    def __init__(self, post):
        self.post = post
        self.attachment = BlogAttachmentsController(self.post)

    def _check_security(self):
        require_access(self.post, 'read')
        if self.post.state == 'draft':
            require_access(self.post, 'write')

    @expose('jinja:forgeblog:templates/blog/post.html')
    @with_trailing_slash
    @validate(dict(page=validators.Int(if_empty=0, if_invalid=0),
                   limit=validators.Int(if_empty=None, if_invalid=None)))
    def index(self, page=0, limit=None, **kw):
        c.form = W.view_post_form
        c.attachment_list = W.attachment_list
        c.subscribe_form = W.subscribe_form
        c.thread = W.thread
        post_count = self.post.discussion_thread.post_count
        limit, page, _ = g.handle_paging(limit, page)
        limit, page = h.paging_sanitizer(limit, page, post_count)
        version = kw.pop('version', None)
        post = self._get_version(version)
        base_post = self.post
        subscribed = M.Mailbox.subscribed(artifact=self.post)
        return dict(post=post, base_post=base_post,
                    page=page, limit=limit, count=post_count,
                    subscribed=subscribed)

    @expose('jinja:forgeblog:templates/blog/edit_post.html')
    @without_trailing_slash
    def edit(self, **kw):
        require_access(self.post, 'write')
        self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
        c.form = W.edit_post_form
        c.attachment_list = W.attachment_list
        return dict(post=self.post)

    @without_trailing_slash
    @expose('jinja:forgeblog:templates/blog/post_history.html')
    def history(self, **kw):
        c.confirmation = W.confirmation
        posts = self.post.history()
        return dict(title=self.post.title, posts=posts)

    @without_trailing_slash
    @expose('jinja:forgeblog:templates/blog/post_diff.html')
    def diff(self, v1, v2, **kw):
        p1 = self._get_version(int(v1))
        p2 = self._get_version(int(v2))
        result = h.diff_text(p1.text, p2.text)
        return dict(p1=p1, p2=p2, edits=result)

    @memorable_forget()
    @expose()
    @require_post()
    @validate(form=W.edit_post_form, error_handler=edit)
    @without_trailing_slash
    def save(self, delete=None, **kw):
        require_access(self.post, 'write')
        self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url())
        if delete:
            self.post.delete()
            flash('Post deleted', 'info')
            redirect(h.really_unicode(c.app.url).encode('utf-8'))
        else:
            g.spam_checker.check(kw['title'] + u'\n' + kw['text'], artifact=self.post,
                                 user=c.user, content_type='blog-post')
        attachment = kw.pop('attachment', None)
        if attachment is not None:
            self.post.add_multiple_attachments(attachment)
        for k, v in kw.iteritems():
            setattr(self.post, k, v)
        self.post.commit()
        redirect('.')

    @without_trailing_slash
    @expose('json:')
    @require_post()
    def update_markdown(self, text=None, **kw):  
        if has_access(self.post, 'edit'):
            self.post.text = text
            self.post.commit()
            g.spam_checker.check(text, artifact=self.post,
                user=c.user, content_type='blog-post')
            return {
                'status' : 'success'
            }
        else:
            return {
                'status' : 'no_permission'
            }

    @expose()
    @without_trailing_slash
    def get_markdown(self):
        return self.post.text

    @without_trailing_slash
    @require_post()
    @expose('json:')
    def revert(self, version, **kw):
        require_access(self.post, 'write')
        orig = self._get_version(version)
        if orig:
            self.post.text = orig.text
        self.post.commit()
        return dict(location='.')

    @expose('json:')
    @require_post()
    @validate(W.subscribe_form)
    def subscribe(self, subscribe=None, unsubscribe=None, **kw):
        if subscribe:
            self.post.subscribe(type='direct')
        elif unsubscribe:
            self.post.unsubscribe()
        return {
            'status': 'ok',
            'subscribed': M.Mailbox.subscribed(artifact=self.post),
            'subscribed_to_tool': M.Mailbox.subscribed(),
        }

    def get_feed(self, project, app, user):
        """Return a :class:`allura.controllers.feed.FeedArgs` object describing
        the xml feed for this controller.

        Overrides :meth:`allura.controllers.feed.FeedController.get_feed`.

        """
        return FeedArgs(
            dict(ref_id=self.post.index_id()),
            'Recent changes to %s' % self.post.title,
            self.post.url())

    def _get_version(self, version):
        if not version:
            return self.post
        try:
            return self.post.get_version(version)
        except ValueError:
            raise exc.HTTPNotFound()


class BlogAdminController(DefaultAdminController):

    @without_trailing_slash
    @expose('jinja:forgeblog:templates/blog/admin_options.html')
    def options(self):
        return dict(app=self.app,
                    allow_config=has_access(self.app, 'configure')())

    @without_trailing_slash
    @expose()
    @require_post()
    def set_options(self, show_discussion=False, allow_email_posting=False):
        self.app.config.options[
            'show_discussion'] = show_discussion and True or False
        self.app.config.options[
            'AllowEmailPosting'] = allow_email_posting and True or False
        flash('Blog options updated')
        redirect(request.referer)

    @without_trailing_slash
    @expose('jinja:forgeblog:templates/blog/admin_exfeed.html')
    def exfeed(self):
        #self.app.external_feeds_list = ['feed1', 'feed2']
        #log.info("EXFEED: %s" % self.app.external_feeds_list)
        feeds_list = []
        for feed in self.app.external_feeds_list:
            feeds_list.append(feed)
        return dict(app=self.app,
                    feeds_list=feeds_list,
                    allow_config=has_access(self.app, 'configure')())

    @without_trailing_slash
    @expose()
    @require_post()
    def set_exfeed(self, new_exfeed=None, **kw):
        exfeed_val = kw.get('exfeed', [])
        if type(exfeed_val) == unicode:
            tmp_exfeed_list = []
            tmp_exfeed_list.append(exfeed_val)
        else:
            tmp_exfeed_list = exfeed_val

        if new_exfeed is not None and new_exfeed != '':
            tmp_exfeed_list.append(new_exfeed)

        exfeed_list = []
        invalid_list = []
        v = validators.URL()
        for link in tmp_exfeed_list:
            try:
                v.to_python(link)
                exfeed_list.append(link)
            except formencode.api.Invalid:
                invalid_list.append(link)

        self.app.external_feeds_list = exfeed_list
        flash('External feeds updated')
        if len(invalid_list) > 0:
            flash('Invalid link(s): %s' %
                  ','.join(link for link in invalid_list), 'error')

        redirect(request.referer)


class RootRestController(BaseController, AppRestControllerMixin):

    def __init__(self):
        self._discuss = AppDiscussionRestController()

    def _check_security(self):
        require_access(c.app, 'read')

    @expose('json:')
    def index(self, title='', text='', state='draft', labels='', limit=10, page=0, **kw):
        if request.method == 'POST':
            require_access(c.app, 'write')
            if BM.BlogPost.is_limit_exceeded(c.app.config, user=c.user):
                log.warn('Create/edit rate limit exceeded. %s', c.app.config.url())
                raise forge_exc.HTTPTooManyRequests()
            post = BM.BlogPost.new(
                title=title,
                state=state,
                text=text,
                labels=labels.split(','),
                **kw)
            return exc.HTTPCreated(headers=dict(Location=h.absurl('/rest' + post.url())))

        else:
            result = RootController().index(limit=limit, page=page)
            posts = result['posts']
            post_titles = []
            for post in posts:
                if has_access(post, 'read')():
                    post_titles.append(
                        {'title': post.title, 'url': h.absurl('/rest' + post.url())})
            return dict(posts=post_titles, count=result['count'], limit=result['limit'], page=result['page'])

    @expose()
    def _lookup(self, year=None, month=None, title=None, *rest):
        if not (year and month and title):
            raise exc.HTTPNotFound()
        slug = '/'.join((year, month, urllib2.unquote(title).decode('utf-8')))
        post = BM.BlogPost.query.get(slug=slug, app_config_id=c.app.config._id)
        if not post:
            raise exc.HTTPNotFound()
        return PostRestController(post), rest


class PostRestController(BaseController):

    def __init__(self, post):
        self.post = post

    def _check_security(self):
        if self.post:
            require_access(self.post, 'read')

    @h.vardec
    @expose('json:')
    def index(self, **kw):
        if request.method == 'POST':
            return self._update_post(**kw)
        else:
            if self.post.state == 'draft':
                require_access(self.post, 'write')
            return self.post.__json__(posts_limit=10)

    def _update_post(self, **post_data):
        require_access(self.post, 'write')
        if BM.BlogPost.is_limit_exceeded(c.app.config, user=c.user):
            log.warn('Create/edit rate limit exceeded. %s', c.app.config.url())
            raise forge_exc.HTTPTooManyRequests()
        if 'delete' in post_data:
            self.post.delete()
            return {}
        if 'title' in post_data:
            self.post.title = post_data['title']
        if 'text' in post_data:
            self.post.text = post_data['text']
        if 'state' in post_data:
            self.post.state = post_data['state']
        if 'labels' in post_data:
            self.post.labels = post_data['labels'].split(',')
        self.post.commit()
        return self.post.__json__(posts_limit=10)
