#       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 urllib
import json
import os

# Non-stdlib imports
from pylons import tmpl_context as c, app_globals as g
from pylons import request
from tg import expose, redirect, flash, validate, jsonify
from tg.decorators import with_trailing_slash
from bson import ObjectId
from ming import schema

# Pyforge-specific imports
from allura import model as M
from allura.app import Application, ConfigOption, SitemapEntry, DefaultAdminController
from allura.lib import helpers as h
from allura.lib.decorators import require_post
from allura.lib.security import require_access, has_access
from allura.lib.utils import JSONForExport

# Local imports
from forgediscussion import model as DM
from forgediscussion import utils
from forgediscussion import version
from .controllers import RootController, RootRestController

from widgets.admin import OptionsAdmin, AddForum


log = logging.getLogger(__name__)


class W:
    options_admin = OptionsAdmin()
    add_forum = AddForum()


class ForgeDiscussionApp(Application):
    __version__ = version.__version__
    permissions = ['configure', 'read',
                   'unmoderated_post', 'post', 'moderate', 'admin']
    permissions_desc = {
        'configure': 'Create new forums.',
        'read': 'View posts.',
        'admin': 'Set permissions. Edit forum properties.',
    }
    config_options = Application.config_options + [
        ConfigOption('PostingPolicy',
                     schema.OneOf('ApproveOnceModerated', 'ModerateAll'), 'ApproveOnceModerated'),
        ConfigOption('AllowEmailPosting', bool, True)
    ]
    PostClass = DM.ForumPost
    AttachmentClass = DM.ForumAttachment
    searchable = True
    exportable = True
    tool_label = 'Discussion'
    tool_description = """
        Discussion forums are a place to talk about any topics related to your project.
        You may set up multiple forums within the Discussion tool.
    """
    default_mount_label = 'Discussion'
    default_mount_point = 'discussion'
    ordinal = 7
    icons = {
        24: 'images/forums_24.png',
        32: 'images/forums_32.png',
        48: 'images/forums_48.png'
    }

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

    def has_access(self, user, topic):
        f = DM.Forum.query.get(shortname=topic.replace('.', '/'),
                               app_config_id=self.config._id)
        return has_access(f, 'post', user=user)()

    def handle_message(self, topic, message):
        log.info('Message from %s (%s)',
                 topic, self.config.options.mount_point)
        log.info('Headers are: %s', message['headers'])
        shortname = urllib.unquote_plus(topic.replace('.', '/'))
        forum = DM.Forum.query.get(
            shortname=shortname, app_config_id=self.config._id)
        if forum is None:
            log.error("Error looking up forum: %r", shortname)
            return
        self.handle_artifact_message(forum, message)

    def main_menu(self):
        '''Apps should provide their entries to be added to the main nav
        :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
        '''
        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 forums(self):
        return DM.Forum.query.find(dict(app_config_id=self.config._id)).all()

    @property
    def top_forums(self):
        return self.subforums_of(None)

    def subforums_of(self, parent_id):
        return DM.Forum.query.find(dict(
            app_config_id=self.config._id,
            parent_id=parent_id,
        )).all()

    def admin_menu(self):
        admin_url = c.project.url() + 'admin/' + \
            self.config.options.mount_point + '/'
        links = []
        if has_access(self, 'configure')():
            links.append(SitemapEntry('Forums', admin_url + 'forums'))
        links += super(ForgeDiscussionApp, self).admin_menu()
        return links

    def sidebar_menu(self):
        try:
            l = []
            moderate_link = None
            forum_links = []
            forums = DM.Forum.query.find(dict(
                app_config_id=c.app.config._id,
                parent_id=None, deleted=False))
            for f in forums:
                if has_access(f, 'read')():
                    if f.url() in request.url and h.has_access(f, 'moderate')():
                        num_moderate = DM.ForumPost.query.find({
                            'discussion_id': f._id,
                            'status': {'$ne': 'ok'},
                            'deleted': False,
                        }).count()
                        moderate_link = SitemapEntry(
                            'Moderate', "%smoderate/" % f.url(), ui_icon=g.icons['moderate'],
                            small=num_moderate)
                    forum_links.append(
                        SitemapEntry(f.name, f.url(), small=f.num_topics))
            url = c.app.url + 'create_topic/'
            url = h.urlquote(
                url + c.forum.shortname if getattr(c, 'forum', None) and c.forum else url)
            l.append(
                SitemapEntry('Create Topic', url, ui_icon=g.icons['add']))
            if has_access(c.app, 'configure')():
                l.append(SitemapEntry('Add Forum', c.app.url +
                         'new_forum', ui_icon=g.icons['conversation']))
                l.append(SitemapEntry('Admin Forums', c.project.url() + 'admin/' +
                         self.config.options.mount_point + '/forums', ui_icon=g.icons['admin']))
            if moderate_link:
                l.append(moderate_link)
            # if we are in a thread and not anonymous, provide placeholder
            # links to use in js
            if '/thread/' in request.url and c.user not in (None, M.User.anonymous()):
                l.append(SitemapEntry(
                    'Mark as Spam', 'flag_as_spam',
                    ui_icon=g.icons['flag'], className='sidebar_thread_spam'))
            l.append(SitemapEntry('Stats Graph', c.app.url +
                     'stats', ui_icon=g.icons['stats']))
            if forum_links:
                l.append(SitemapEntry('Forums'))
                l = l + forum_links
            l.append(SitemapEntry('Help'))
            l.append(
                SitemapEntry('Formatting Help', c.app.url + 'markdown_syntax'))
            return l
        except:  # pragma no cover
            log.exception('sidebar_menu')
            return []

    def install(self, project):
        'Set up any default permissions and roles here'
        # Don't call super install here, as that sets up discussion for a tool

        # 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, 'moderate'),
            M.ACE.allow(role_admin, 'configure'),
            M.ACE.allow(role_admin, 'admin'),
        ]

        utils.create_forum(self, new_forum=dict(
            shortname='general',
            create='on',
            name='General Discussion',
            description='Forum about anything you want to talk about.',
            parent='',
            members_only=False,
            anon_posts=False,
            monitoring_email=None))

    def uninstall(self, project):
        "Remove all the tool's artifacts from the database"
        DM.Forum.query.remove(dict(app_config_id=self.config._id))
        DM.ForumThread.query.remove(dict(app_config_id=self.config._id))
        DM.ForumPost.query.remove(dict(app_config_id=self.config._id))
        super(ForgeDiscussionApp, self).uninstall(project)

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

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


class ForumAdminController(DefaultAdminController):

    def _check_security(self):
        require_access(self.app, 'admin')

    @with_trailing_slash
    def index(self, **kw):
        redirect('forums')

    @expose('jinja:forgediscussion:templates/discussionforums/admin_options.html')
    def options(self):
        c.options_admin = W.options_admin
        return dict(app=self.app,
                    form_value=dict(
                        PostingPolicy=self.app.config.options.get('PostingPolicy'),
                        AllowEmailPosting=self.app.config.options.get('AllowEmailPosting', True)))

    @expose('jinja:forgediscussion:templates/discussionforums/admin_forums.html')
    def forums(self, add_forum=None, **kw):
        c.add_forum = W.add_forum
        return dict(app=self.app,
                    allow_config=has_access(self.app, 'configure')())

    @h.vardec
    @expose()
    @require_post()
    def update_forums(self, forum=None, **kw):
        if forum is None:
            forum = []
        for f in forum:
            forum = DM.Forum.query.get(_id=ObjectId(str(f['id'])))
            if f.get('delete'):
                forum.deleted = True
            elif f.get('undelete'):
                forum.deleted = False
            else:
                if '.' in f['shortname'] or '/' in f['shortname'] or ' ' in f['shortname']:
                    flash('Shortname cannot contain space . or /', 'error')
                    redirect('.')
                forum.name = f['name']
                forum.shortname = f['shortname']
                forum.description = f['description']
                forum.monitoring_email = f['monitoring_email']
                if 'members_only' in f:
                    if 'anon_posts' in f:
                        flash(
                            'You cannot have anonymous posts in a members only forum.', 'warning')
                        forum.anon_posts = False
                        del f['anon_posts']
                    forum.members_only = True
                else:
                    forum.members_only = False
                if 'anon_posts' in f:
                    forum.anon_posts = True
                else:
                    forum.anon_posts = False
                role_anon = M.ProjectRole.anonymous()._id
                if forum.members_only:
                    role_developer = M.ProjectRole.by_name('Developer')._id
                    forum.acl = [
                        M.ACE.allow(role_developer, M.ALL_PERMISSIONS),
                        M.DENY_ALL]
                elif forum.anon_posts:
                    forum.acl = [M.ACE.allow(role_anon, 'post')]
                else:
                    forum.acl = []
        flash('Forums updated')
        redirect(request.referrer)

    @h.vardec
    @expose()
    @require_post()
    @validate(form=W.add_forum, error_handler=forums)
    def add_forum(self, add_forum=None, **kw):
        f = utils.create_forum(self.app, add_forum)
        redirect(f.url())
