#       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.

from __future__ import unicode_literals
from __future__ import absolute_import
import json
import logging

import six
from six.moves.urllib.parse import unquote
from datetime import date, datetime, timedelta, time
import calendar
from collections import OrderedDict


from tg import expose, validate, redirect, flash
from tg.decorators import with_trailing_slash, without_trailing_slash
from tg import tmpl_context as c, app_globals as g
from tg import request
from formencode import validators
from webob import exc
import pymongo

from allura.lib.security import require_access, has_access, require_authenticated
from allura.lib.search import search_app
from allura.lib import helpers as h
from allura.lib import validators as v
from allura.lib.utils import AntiSpam, permanent_redirect
from allura.lib.decorators import require_post, memorable_forget
from allura.controllers import BaseController, DispatchIndex
from allura.controllers.rest import AppRestControllerMixin
from allura.controllers.feed import FeedArgs, FeedController
from allura import model as M

from .forum import ForumController
from forgediscussion import import_support
from forgediscussion import model
from forgediscussion import utils
from forgediscussion import widgets as FW
from allura.lib.widgets import discuss as DW
from allura.lib.widgets.search import SearchResults, SearchHelp

from forgediscussion.widgets.admin import AddForumShort

log = logging.getLogger(__name__)


class RootController(BaseController, DispatchIndex, FeedController):

    class W(object):
        new_topic = DW.NewTopicPost(submit_text='Post')

        announcements_table = FW.AnnouncementsTable()
        add_forum = AddForumShort()
        search_results = SearchResults()
        search_help = SearchHelp(comments=False, history=False,
                                 fields={'author_user_name_t': 'Username',
                                         'text': '"Post text"',
                                         'timestamp_dt': 'Date posted.  Example: timestamp_dt:[2018-01-01T00:00:00Z TO *]',
                                         'name_s': 'Subject'})

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

    @with_trailing_slash
    @expose('jinja:forgediscussion:templates/discussionforums/index.html')
    def index(self, new_forum=False, **kw):
        c.add_forum = self.W.add_forum
        c.announcements_table = self.W.announcements_table
        announcements = model.ForumThread.query.find(dict(
            app_config_id=c.app.config._id,
            flags='Announcement',
        )).all()
        forums = model.Forum.query.find(dict(
            app_config_id=c.app.config._id,
            parent_id=None, deleted=False)).all()
        forums = [f for f in forums if h.has_access(f, 'read')()]
        return dict(forums=forums,
                    announcements=announcements,
                    hide_forum=(not new_forum))

    @expose('jinja:forgediscussion:templates/discussionforums/index.html')
    def new_forum(self, **kw):
        require_access(c.app, 'configure')
        return self.index(new_forum=True, **kw)

    @h.vardec
    @expose()
    @require_post()
    @validate(form=W.add_forum, error_handler=index)
    def add_forum_short(self, add_forum=None, **kw):
        require_access(c.app, 'configure')
        f = utils.create_forum(c.app, add_forum)
        redirect(f.url())

    @with_trailing_slash
    @expose('jinja:forgediscussion:templates/discussionforums/create_topic.html')
    def create_topic(self, forum_name=None, new_forum=False, **kw):
        forums = model.Forum.query.find(dict(app_config_id=c.app.config._id,
                                             parent_id=None,
                                             deleted=False))
        c.new_topic = self.W.new_topic
        my_forums = []
        forum_name = h.really_unicode(unquote(forum_name)) if forum_name else None
        current_forum = None
        for f in forums:
            if forum_name == f.shortname:
                current_forum = f
            if has_access(f, 'post')():
                my_forums.append(f)
        return dict(forums=my_forums,
                    current_forum=current_forum,
                    subscribed=M.Mailbox.subscribed(artifact=current_forum),
                    subscribed_to_tool=M.Mailbox.subscribed(),
                    )

    @memorable_forget()
    @h.vardec
    @expose()
    @require_post()
    @validate(W.new_topic, error_handler=create_topic)
    @AntiSpam.validate('Spambot protection engaged', error_url='create_topic')
    def save_new_topic(self, subject=None, text=None, forum=None, subscribe=False, **kw):
        self.rate_limit(model.ForumPost, 'Topic creation', six.ensure_text(request.referer or '/'))
        discussion = model.Forum.query.get(
            app_config_id=c.app.config._id,
            shortname=forum)
        if discussion.deleted and not has_access(c.app, 'configure')():
            flash('This forum has been removed.')
            redirect(six.ensure_text(request.referer or '/'))
        require_access(discussion, 'post')
        thd = discussion.get_discussion_thread(dict(
            headers=dict(Subject=subject)))[0]
        p = thd.post(subject, text, subscribe=subscribe)
        if 'attachment' in kw:
            p.add_multiple_attachments(kw['attachment'])
        thd.post_to_feed(p)
        flash('Message posted')
        redirect(thd.url())

    @with_trailing_slash
    @expose('jinja:forgediscussion:templates/discussionforums/search.html')
    @validate(dict(q=v.UnicodeString(if_empty=None),
                   history=validators.StringBool(if_empty=False),
                   project=validators.StringBool(if_empty=False),
                   limit=validators.Int(if_empty=None, if_invalid=None),
                   page=validators.Int(if_empty=0, if_invalid=0)))
    def search(self, q=None, history=None, project=None, limit=None, page=0, **kw):
        c.search_results = self.W.search_results
        c.help_modal = self.W.search_help
        search_params = kw
        search_params.update({
            'q': q or '',
            'history': history,
            'project': project,
            'limit': limit,
            'page': page,
            'allowed_types': ['Post', 'Post Snapshot', 'Discussion', 'Thread'],
        })
        d = search_app(**search_params)
        d['search_comments_disable'] = True
        return d

    @expose()
    def markdown_syntax(self, **kw):
        permanent_redirect('/nf/markdown_syntax')

    @expose()
    def _lookup(self, id=None, *remainder):
        if id:
            id = unquote(id)
            forum = model.Forum.query.get(
                app_config_id=c.app.config._id,
                shortname=id)
            if forum is None:
                raise exc.HTTPNotFound()
            c.forum = forum
            return ForumController(id), remainder
        else:
            raise exc.HTTPNotFound()

    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),
            'Recent posts to %s' % app.config.options.mount_label,
            app.url)

    @without_trailing_slash
    @expose('jinja:forgediscussion:templates/discussionforums/stats_graph.html')
    def stats(self, dates=None, forum=None, **kw):
        if not dates:
            dates = "{} to {}".format(
                (date.today() - timedelta(days=60)).strftime('%Y-%m-%d'),
                date.today().strftime('%Y-%m-%d'))
        return dict(
            dates=dates,
            selected_forum=forum,
        )

    @expose('json:')
    @validate(dict(
        begin=h.DateTimeConverter(not_empty=True),
        end=h.DateTimeConverter(not_empty=True),
    ), error_handler=exc.HTTPBadRequest)
    def stats_data(self, begin=None, end=None, forum=None, **kw):
        end = end or date.today()
        begin = begin or end - timedelta(days=60)

        discussion_id_q = {
            '$in': [d._id for d in c.app.forums
                    if d.shortname == forum or not forum]
        }
        # must be ordered dict, so that sorting by this works properly
        grouping = OrderedDict()
        grouping['year'] = {'$year': '$timestamp'}
        grouping['month'] = {'$month': '$timestamp'}
        grouping['day'] = {'$dayOfMonth': '$timestamp'}
        mongo_data = model.ForumPost.query.aggregate([
            {'$match': {
                'discussion_id': discussion_id_q,
                'status': 'ok',
                'timestamp': {
                    # convert date to datetime to make pymongo happy
                    '$gte': datetime.combine(begin, time.min),
                    '$lte': datetime.combine(end, time.max),
                },
                'deleted': False,
            }},
            {'$group': {
                '_id': grouping,
                'posts': {'$sum': 1},
            }},
            {'$sort': {
                '_id': pymongo.ASCENDING,
            }},
        ], cursor={})

        def reformat_data(mongo_data):
            def item(day, val):
                return [
                    calendar.timegm(day.timetuple()) * 1000,
                    val
                ]

            next_expected_date = begin
            for d in mongo_data:
                this_date = datetime(
                    d['_id']['year'], d['_id']['month'], d['_id']['day'])
                for day in h.daterange(next_expected_date, this_date):
                    yield item(day, 0)
                yield item(this_date, d['posts'])
                next_expected_date = this_date + timedelta(days=1)
            for day in h.daterange(next_expected_date, end + timedelta(days=1)):
                yield item(day, 0)

        return dict(
            begin=begin,
            end=end,
            data=list(reformat_data(mongo_data)),
        )


class RootRestController(BaseController, AppRestControllerMixin):

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

    @expose()
    def _lookup(self, forum, *remainder):
        return ForumRestController(unquote(forum)), remainder

    @expose('json:')
    def index(self, limit=None, page=0, **kw):
        limit, page, start = g.handle_paging(limit, int(page))
        forums = model.Forum.query.find(dict(
            app_config_id=c.app.config._id,
            parent_id=None, deleted=False)
        ).sort([('shortname', pymongo.ASCENDING)]).skip(start).limit(limit)
        count = forums.count()
        json = dict(forums=[dict(_id=f._id,
                                 name=f.name,
                                 shortname=f.shortname,
                                 description=f.description,
                                 num_topics=f.num_topics,
                                 last_post=f.last_post,
                                 url=h.absurl('/rest' + f.url()))
                            for f in forums if has_access(f, 'read')])
        json['limit'] = limit
        json['page'] = page
        json['count'] = count
        return json

    @expose('json:')
    def validate_import(self, doc=None, username_mapping=None, **kw):
        require_access(c.project, 'admin')
        if username_mapping is None:
            username_mapping = {}
        try:
            doc = json.loads(doc)
            warnings, doc = import_support.validate_import(
                doc, username_mapping)
            return dict(warnings=warnings, errors=[])
        except Exception as e:
            raise
            log.exception(e)
            return dict(status=False, errors=[repr(e)])

    @expose('json:')
    def perform_import(
            self, doc=None, username_mapping=None, default_username=None, create_users=False,
            **kw):
        require_access(c.project, 'admin')
        if username_mapping is None:
            username_mapping = '{}'
        if not c.api_token.can_import_forum():
            log.error('Import capability is not enabled for %s', c.project.shortname)
            raise exc.HTTPForbidden(detail='Import is not allowed')
        try:
            doc = json.loads(doc)
            username_mapping = json.loads(username_mapping)
            warnings = import_support.perform_import(
                doc, username_mapping, default_username, create_users)
            return dict(warnings=warnings, errors=[])
        except Exception as e:
            raise
            log.exception(e)
            return dict(status=False, errors=[str(e)])


class ForumRestController(BaseController):

    def __init__(self, forum):
        self.forum = model.Forum.query.get(
            app_config_id=c.app.config._id,
            shortname=forum)
        if not self.forum or self.forum.deleted:
            raise exc.HTTPNotFound()

    def _check_security(self):
        require_access(self.forum, 'read')

    @expose('json:')
    def index(self, limit=None, page=0, **kw):
        limit, page, start = g.handle_paging(limit, int(page))
        topics = model.Forum.thread_class().query.find(dict(discussion_id=self.forum._id))
        topics = topics.sort([('flags', pymongo.DESCENDING),
                              ('last_post_date', pymongo.DESCENDING)])
        topics = topics.skip(start).limit(limit)
        count = topics.count()
        json = {}
        json['forum'] = self.forum.__json__(limit=1)  # small limit since we're going to "del" the threads anyway
        # topics replace threads here
        del json['forum']['threads']
        json['forum']['topics'] = [dict(_id=t._id,
                                        subject=t.subject,
                                        num_replies=t.num_replies,
                                        num_views=t.num_views,
                                        url=h.absurl('/rest' + t.url()),
                                        last_post=t.last_post)
                                   for t in topics if t.status == 'ok']
        json['count'] = count
        json['page'] = page
        json['limit'] = limit
        return json

    @expose()
    def _lookup(self, thread, thread_id, *remainder):
        if thread == 'thread':
            topic = model.Forum.thread_class().query.find(dict(
                app_config_id=c.app.config._id,
                discussion_id=self.forum._id,
                _id=unquote(thread_id))).first()
            if topic:
                return ForumTopicRestController(self.forum, topic), remainder
        raise exc.HTTPNotFound()


class ForumTopicRestController(BaseController):

    def __init__(self, forum, topic):
        self.forum = forum
        self.topic = topic

    def _check_security(self):
        require_access(self.forum, 'read')

    @expose('json:')
    def index(self, limit=None, page=0, **kw):
        limit, page, start = g.handle_paging(limit, int(page))
        json_data = {}
        json_data['topic'] = self.topic.__json__(limit=limit, page=page)
        json_data['count'] = self.topic.query_posts(status='ok').count()
        json_data['page'] = page
        json_data['limit'] = limit
        return json_data
