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

import re
import logging
from datetime import datetime, timedelta

import six
from urllib.parse import unquote

from bson import ObjectId
from tg import expose, flash, redirect, validate, request, config, session
from tg.decorators import with_trailing_slash, without_trailing_slash
from tg import tmpl_context as c, app_globals as g
from paste.deploy.converters import asbool
from webob import exc
import jinja2
import markupsafe
import pymongo

from ming.utils import LazyProperty

from allura import model as M
from allura.app import SitemapEntry
from allura.lib import helpers as h
from allura.lib.helpers import iter_entry_points
from allura.lib import utils
from allura.lib.decorators import require_post
from allura.controllers.feed import FeedArgs, FeedController
from allura.controllers.rest import nbhd_lookup_first_path
from allura.lib.security import require_access
from allura.lib.security import RoleCache
from allura.lib.widgets import forms as ff
from allura.lib.widgets import form_fields as ffw
from allura.lib.widgets import project_list as plw
from allura.lib import plugin, exceptions
from .search import ProjectBrowseController
from allura.ext.user_profile.user_main import UserProfileApp

log = logging.getLogger(__name__)


class W:
    resize_editor = ffw.AutoResizeTextarea()
    project_summary = plw.ProjectSummary()
    add_project = plugin.ProjectRegistrationProvider.get().add_project_widget(antispam=True)
    page_list = ffw.PageList()
    page_size = ffw.PageSize()
    neighborhood_overview_form = ff.NeighborhoodOverviewForm()
    award_grant_form = ff.AwardGrantForm


class NeighborhoodController:

    '''Manages a neighborhood of projects.
    '''

    def __init__(self, neighborhood):
        self.neighborhood = neighborhood
        self.neighborhood_name = self.neighborhood.name
        self.browse = NeighborhoodProjectBrowseController(neighborhood=self.neighborhood)
        # 'admin' without underscore will pass through to _lookup which will find the regular "admin" tool mounted
        # on the --init-- Project record for this neighborhood.
        self._admin = NeighborhoodAdminController(self.neighborhood)
        self._moderate = NeighborhoodModerateController(self.neighborhood)
        self.import_project = ProjectImporterController(self.neighborhood)

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

    def _before(self, *args, **kwargs):
        # TurboGears runs this before each request
        c.project = self.neighborhood.neighborhood_project

    @expose()
    def _lookup(self, pname, *remainder):
        c.project, remainder = nbhd_lookup_first_path(self.neighborhood, pname, c.user, remainder)
        return ProjectController(), remainder

    @expose('jinja:allura:templates/neighborhood_project_list.html')
    @with_trailing_slash
    def index(self, sort='alpha', limit=25, page=0, **kw):
        text = None
        if self.neighborhood.use_wiki_page_as_root:
            default_wiki_page = get_default_wiki_page()
            if default_wiki_page:
                text = default_wiki_page.html_text
        elif self.neighborhood.redirect:
            redirect(self.neighborhood.redirect)
        elif not self.neighborhood.has_home_tool:
            mount = c.project.ordered_mounts()[0]
            if mount is not None:
                if 'ac' in mount:
                    redirect(mount['ac'].options.mount_point + '/')
                elif 'sub' in mount:
                    redirect(mount['sub'].url())
            else:
                redirect(c.project.app_configs[0].options.mount_point + '/')
        else:
            text = g.markdown.cached_convert(
                self.neighborhood, 'homepage'),

        c.project_summary = W.project_summary
        c.page_list = W.page_list
        limit, page, start = g.handle_paging(limit, page)
        pq = M.Project.query.find(dict(
            neighborhood_id=self.neighborhood._id,
            deleted=False,
            is_nbhd_project=False,
        ))
        if sort == 'alpha':
            pq.sort('name')
        else:
            pq.sort('last_updated', pymongo.DESCENDING)
        count = pq.count()
        nb_max_projects = self.neighborhood.get_max_projects()
        projects = pq.skip(start).limit(int(limit)).all()
        categories = M.ProjectCategory.query.find(
            {'parent_id': None}).sort('name').all()
        c.custom_sidebar_menu = []
        if h.has_access(self.neighborhood, 'register') and (nb_max_projects is None or count < nb_max_projects):
            c.custom_sidebar_menu += [
                SitemapEntry('Add a Project', self.neighborhood.url()
                             + 'add_project', ui_icon=g.icons['add']),
                SitemapEntry('')
            ]
        c.custom_sidebar_menu = c.custom_sidebar_menu + [
            SitemapEntry(cat.label, self.neighborhood.url() + 'browse/' + cat.name) for cat in categories
        ]
        return dict(neighborhood=self.neighborhood,
                    title="Welcome to " + self.neighborhood.name,
                    text=text,
                    projects=projects,
                    sort=sort,
                    limit=limit, page=page, count=count)

    @expose('jinja:allura:templates/neighborhood_add_project.html')
    @without_trailing_slash
    def add_project(self, **form_data):
        with h.login_overlay():
            require_access(self.neighborhood, 'register')
        verify = request.validation.errors == {'_the_form': 'phone-verification'}
        c.show_phone_verification_overlay = verify
        c.add_project = W.add_project
        form_data.setdefault('tools', W.add_project.default_tools)
        form_data['neighborhood'] = self.neighborhood.name
        return dict(neighborhood=self.neighborhood, form_data=form_data)

    @expose('jinja:allura:templates/phone_verification_fragment.html')
    def phone_verification_fragment(self, *args, **kw):
        require_access(self.neighborhood, 'register')
        return {}

    @expose('json:')
    def verify_phone(self, number, **kw):
        require_access(self.neighborhood, 'register')
        p = plugin.ProjectRegistrationProvider.get()
        result = p.verify_phone(c.user, number)
        request_id = result.pop('request_id', None)
        if request_id:
            session['phone_verification.request_id'] = request_id
            number_hash = utils.phone_number_hash(number)
            session['phone_verification.number_hash'] = number_hash
            session.save()
        if 'error' in result:
            result['error'] = markupsafe.Markup.escape(result['error'])
            result['error'] = h.really_unicode(result['error'])
        return result

    @expose('json:')
    def check_phone_verification(self, pin, **kw):
        require_access(self.neighborhood, 'register')
        p = plugin.ProjectRegistrationProvider.get()
        request_id = session.get('phone_verification.request_id')
        number_hash = session.get('phone_verification.number_hash')
        res = p.check_phone_verification(c.user, request_id, pin, number_hash)
        if 'error' in res:
            res['error'] = markupsafe.Markup.escape(res['error'])
            res['error'] = h.really_unicode(res['error'])
        return res

    @expose('json:')
    @validate(W.add_project)
    def check_names(self, **raw_data):
        require_access(self.neighborhood, 'register')
        return request.validation.errors

    @h.vardec
    @expose()
    @validate(W.add_project, error_handler=add_project)
    @utils.AntiSpam.validate('Spambot protection engaged')
    @require_post()
    def register(
            self, project_unixname=None, project_description=None, project_name=None, neighborhood=None,
            private_project=None, tools=None, **kw):
        require_access(self.neighborhood, 'register')
        if private_project:
            require_access(self.neighborhood, 'admin')
        neighborhood = M.Neighborhood.query.get(name=neighborhood)

        project_description = h.really_unicode(project_description or '')
        project_name = h.really_unicode(project_name or '')
        project_unixname = h.really_unicode(project_unixname or '').lower()
        try:
            c.project = neighborhood.register_project(project_unixname,
                                                      project_name=project_name, private_project=private_project)
        except exceptions.ProjectOverlimitError:
            flash(
                "You have exceeded the maximum number of projects you are allowed to create", 'error')
            redirect('add_project')
        except exceptions.ProjectRatelimitError:
            flash(
                "Project creation rate limit exceeded.  Please try again later.", 'error')
            redirect('add_project')
        except exceptions.ProjectPhoneVerificationError:
            flash('You must pass phone verification', 'error')
            redirect('add_project')
        except Exception as e:
            log.error('error registering project: %s',
                      project_unixname, exc_info=True)
            flash('Internal Error. Please try again later.', 'error')
            redirect('add_project')

        if project_description:
            c.project.short_description = project_description
        offset = c.project.next_mount_point(include_hidden=True)
        if tools and not neighborhood.project_template:
            anchored_tools = neighborhood.get_anchored_tools()
            install_params = []
            for i, tool in enumerate(tools):
                if (tool.lower() not in list(anchored_tools.keys())) and (c.project.app_instance(tool) is None):
                    install_params.append(dict(ep_name=tool, ordinal=i + offset))
            c.project.install_apps(install_params)
        redirect(c.project.script_name + 'admin/?first-visit')

    @expose()
    def icon(self, w=None, **kw):
        try:
            if isinstance(w, list):
                w = w[0]
            icon = c.project.icon_sized(w=int(w or 48))
        except ValueError as e:
            log.info('Invalid project icon size: %s on %s', e, request.url)
            icon = None
        if icon is None and w is None:
            # fallback to older icons stored with neighborhood_id rather than using the nbhd project_id
            icon = self.neighborhood.icon
        if not icon:
            raise exc.HTTPNotFound
        return icon.serve()

    @expose('json:')
    def users(self, **kw):
        p = self.neighborhood.neighborhood_project
        return {
            'options': [{
                'value': u.username,
                'label': f'{u.display_name} ({u.username})'
            } for u in p.users()]
        }


class NeighborhoodProjectBrowseController(ProjectBrowseController):

    def __init__(self, neighborhood=None, category_name=None, parent_category=None):
        self.neighborhood = neighborhood
        super().__init__(
            category_name=category_name, parent_category=parent_category)
        self.nav_stub = '%sbrowse/' % self.neighborhood.url()
        self.additional_filters = {'neighborhood_id': self.neighborhood._id}

    @expose()
    def _lookup(self, category_name, *remainder):
        c.project = self.neighborhood.neighborhood_project
        category_name = unquote(category_name)
        return NeighborhoodProjectBrowseController(neighborhood=self.neighborhood, category_name=category_name,
                                                   parent_category=self.category), remainder

    @expose('jinja:allura:templates/neighborhood_project_list.html')
    @without_trailing_slash
    def index(self, sort='alpha', limit=25, page=0, **kw):
        c.project_summary = W.project_summary
        c.page_list = W.page_list
        limit, page, start = g.handle_paging(limit, page)
        projects, count = self._find_projects(
            sort=sort, limit=limit, start=start)
        title = self._build_title()
        c.custom_sidebar_menu = self._build_nav()
        return dict(projects=projects,
                    title=title,
                    text=None,
                    neighborhood=self.neighborhood,
                    sort=sort,
                    limit=limit, page=page, count=count)


class ToolListController:

    """Renders a list of all tools of a given type in the current project."""

    @expose('jinja:allura:templates/tool_list.html')
    def _default(self, tool_name=None, page=0, limit=200, **kw):
        if tool_name is None:
            raise exc.HTTPNotFound
        c.page_list = W.page_list
        tool_name = tool_name.lower()
        entries = c.project.sitemap(included_tools=[tool_name],
                                    tools_only=True, per_tool_limit=None)
        total_entries = len(entries)
        limit, page = h.paging_sanitizer(limit, page, total_entries)
        start = page * limit
        tool_label = g.entry_points['tool'][tool_name].tool_label if entries else None
        return dict(
            page=page,
            limit=limit,
            total_entries=total_entries,
            entries=entries[start:start + limit],
            type=tool_label,
            tool_name=h.pluralize_tool_name(tool_label, total_entries),
        )


class ProjectController(FeedController):

    def __init__(self):
        self.screenshot = ScreenshotsController()
        self._list = ToolListController()

    @expose('json:')
    def _nav(self, admin_options=False, **kw):
        return c.project.nav_data(admin_options=admin_options)

    @expose()
    def _lookup(self, name, *remainder):
        name = unquote(name)
        name = six.ensure_text(name)  # we don't support unicode names, but in case a url comes in with one
        if name == '_nav.json':
            return self, ['_nav']

        if c.project.deleted:
            if c.user not in c.project.admins():
                raise exc.HTTPNotFound(name)
        app = c.project.app_instance(name)

        if app:
            c.app = app
            if app.root:
                return app.root, remainder
        subproject = M.Project.query.get(
            shortname=c.project.shortname + '/' + name,
            neighborhood_id=c.project.neighborhood_id)
        if subproject:
            c.project = subproject
            c.app = None
            return ProjectController(), remainder

        if c.project.is_nbhd_project:
            raise exc.HTTPNotFound(name)
        else:
            # if a tool under a project doesn't exist, redirect to the first valid tool instead of 404
            self.index()

    @expose('jinja:allura:templates/members.html')
    @with_trailing_slash
    def _members(self, **kw):
        users = []
        admins = []
        developers = []
        for user in c.project.users():
            roles = M.ProjectRole.query.find(
                {'_id': {'$in': M.ProjectRole.by_user(user).roles}})
            roles = {r.name for r in roles}
            _user = user
            _user['roles'] = ', '.join(sorted(roles))
            if 'Admin' in roles:
                admins.append(_user)
            elif 'Developer' in roles:
                developers.append(_user)
            else:
                users.append(_user)

        def get_username(user): return user['username']
        admins = sorted(admins, key=get_username)
        developers = sorted(developers, key=get_username)
        users = sorted(users, key=get_username)
        return dict(users=admins + developers + users)

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

    @expose()
    def index(self, **kw):
        mount, app = c.project.first_mount_visible(c.user)
        if mount is not None:
            if hasattr(app, 'default_redirect'):
                app.default_redirect()
            args = dict(redirect_with=exc.HTTPMovedPermanently)
            # Application has property; Subproject has method
            redirect(app.url() if callable(app.url) else app.url, **args)
        else:
            redirect(c.project.app_configs[0].url(), redirect_with=exc.HTTPMovedPermanently)

    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),
            'Recent changes to Project %s' % project.name,
            project.url())

    @expose()
    def icon(self, w=48, **kw):
        try:
            if isinstance(w, list):
                w = w[0]
            icon = c.project.icon_sized(w=int(w))
        except ValueError as e:
            log.info('Invalid project icon size: %s on %s', e, request.url)
            icon = None
        if not icon:
            raise exc.HTTPNotFound
        return icon.serve()

    @expose()
    def user_icon(self, **kw):
        try:
            return self.icon(**kw)
        except exc.HTTPNotFound:
            if config.get('default_avatar_image'):
                default_image_url = config['default_avatar_image']
            else:
                default_image_url = g.forge_static('images/user.png')
            redirect(default_image_url)

    @expose('json:')
    def user_search(self, term='', **kw):
        if len(term) < 3:
            raise exc.HTTPBadRequest('"term" param must be at least length 3')
        named_roles = RoleCache(
            g.credentials,
            g.credentials.project_roles(project_id=c.project.root_project._id).named)
        users = M.User.query.find({
            '_id': {'$in': named_roles.userids_that_reach},
            'display_name': re.compile(r'(?i)%s' % re.escape(term)),
            'disabled': False,
            'pending': False,
        }).sort('username').limit(10).all()
        return dict(
            users=[
                dict(
                    label='{} ({})'.format(u.get_pref('display_name'), u.username),
                    value=u.username,
                    id=u.username)
                for u in users])

    @expose('json:')
    def users(self, **kw):
        users = c.project.users()
        if c.user and c.user in users:
            users.remove(c.user)
            users.insert(0, c.user)

        return {
            'options': [{
                'value': u.username,
                'label': f'{u.display_name} ({u.username})'
            } for u in users]
        }


class ScreenshotsController:

    @expose()
    def _lookup(self, filename, *args):
        if args:
            filename = unquote(filename)
        else:
            filename = unquote(request.path.rsplit('/', 1)[-1])
        return ScreenshotController(filename), args


class ScreenshotController:

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

    @expose()
    def index(self, embed=True, **kw):
        return self._screenshot.serve(embed)

    @expose()
    def thumb(self, embed=True, **kwargs):
        return self._thumb.serve(embed)

    @LazyProperty
    def _screenshot(self):
        f = M.ProjectFile.query.get(
            project_id=c.project._id,
            category='screenshot',
            filename=self.filename)
        if not f:
            raise exc.HTTPNotFound
        return f

    @LazyProperty
    def _thumb(self):
        f = M.ProjectFile.query.get(
            project_id=c.project._id,
            category='screenshot_thumb',
            filename=self.filename)
        if not f:
            raise exc.HTTPNotFound
        return f


def set_nav(neighborhood):
    project = neighborhood.neighborhood_project
    if project:
        c.project = project
        g.set_app('admin')
    else:
        admin_url = neighborhood.url() + '_admin/'
        c.custom_sidebar_menu = [
            SitemapEntry('Overview', admin_url + 'overview'),
            SitemapEntry('Awards', admin_url + 'accolades')]


class NeighborhoodAdminController:

    def __init__(self, neighborhood):
        self.neighborhood = neighborhood
        self.awards = NeighborhoodAwardsController(self.neighborhood)
        self.stats = NeighborhoodStatsController(self.neighborhood)

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

    @with_trailing_slash
    @expose()
    def index(self, **kw):
        utils.permanent_redirect('overview')

    @without_trailing_slash
    @expose('jinja:allura:templates/neighborhood_admin_overview.html')
    def overview(self, **kw):
        set_nav(self.neighborhood)
        c.overview_form = W.neighborhood_overview_form
        allow_undelete = asbool(config.get('allow_project_undelete', True))
        allow_wiki_as_root = bool(get_default_wiki_page())

        return dict(
            neighborhood=self.neighborhood,
            allow_project_undelete=allow_undelete,
            allow_wiki_as_root=allow_wiki_as_root)

    @without_trailing_slash
    @expose('jinja:allura:templates/neighborhood_admin_permissions.html')
    def permissions(self):
        set_nav(self.neighborhood)
        return dict(neighborhood=self.neighborhood)

    @expose('json:')
    def project_search(self, term='', **kw):
        if len(term) < 3:
            raise exc.HTTPBadRequest('"term" param must be at least length 3')
        project_regex = re.compile('(?i)%s' % re.escape(term))
        projects = M.Project.query.find(dict(
            neighborhood_id=self.neighborhood._id, deleted=False,
            shortname=project_regex)).sort('shortname')
        return dict(
            projects=[
                dict(
                    label=p.shortname,
                    value=p.shortname,
                    id=p.shortname)
                for p in projects])

    @without_trailing_slash
    @expose('jinja:allura:templates/neighborhood_admin_accolades.html')
    def accolades(self):
        set_nav(self.neighborhood)
        awards = M.Award.query.find(
            dict(created_by_neighborhood_id=self.neighborhood._id)).all()
        awards_count = len(awards)
        grants = M.AwardGrant.query.find(
            dict(granted_by_neighborhood_id=self.neighborhood._id))
        grants_count = grants.count()
        c.award_grant_form = W.award_grant_form(
            awards=awards,
            project_select_url=self.neighborhood.url() + '_admin/project_search')
        return dict(
            awards=awards,
            awards_count=awards_count,
            grants=grants,
            grants_count=grants_count,
            neighborhood=self.neighborhood)

    @expose()
    @require_post()
    @validate(W.neighborhood_overview_form, error_handler=overview)
    def update(self, name=None, css=None, homepage=None, project_template=None, icon=None, **kw):
        nbhd = self.neighborhood
        c.project = nbhd.neighborhood_project
        h.log_if_changed(nbhd, 'name', name,
                         'change neighborhood name to %s' % name)
        nbhd_redirect = kw.pop('redirect', '')
        h.log_if_changed(nbhd, 'redirect', nbhd_redirect,
                         'change neighborhood redirect to %s' % nbhd_redirect)
        h.log_if_changed(nbhd, 'homepage', homepage,
                         'change neighborhood homepage to %s' % homepage)
        h.log_if_changed(nbhd, 'css', css,
                         'change neighborhood css to %s' % css)
        h.log_if_changed(nbhd, 'project_template', project_template,
                         'change neighborhood project template to %s'
                         % project_template)
        allow_browse = kw.get('allow_browse', False)
        h.log_if_changed(nbhd, 'allow_browse', allow_browse,
                         'change neighborhood allow browse to %s'
                         % allow_browse)
        show_title = kw.get('show_title', False)
        h.log_if_changed(nbhd, 'show_title', show_title,
                         'change neighborhood show title to %s' % show_title)
        use_wiki_page_as_root = kw.get('use_wiki_page_as_root', False)
        h.log_if_changed(nbhd, 'use_wiki_page_as_root', use_wiki_page_as_root,
                         'change use wiki page as root to %s' % use_wiki_page_as_root)
        project_list_url = kw.get('project_list_url', '')
        h.log_if_changed(nbhd, 'project_list_url', project_list_url,
                         'change neighborhood project list url to %s'
                         % project_list_url)
        tracking_id = kw.get('tracking_id', '')
        h.log_if_changed(nbhd, 'tracking_id', tracking_id,
                         'update neighborhood tracking_id')
        prohibited_tools = kw.get('prohibited_tools', '')

        result = True
        if prohibited_tools.strip() != '':
            for prohibited_tool in prohibited_tools.split(','):
                if prohibited_tool.strip() not in g.entry_points['tool']:
                    flash('Prohibited tools "%s" is invalid' %
                          prohibited_tool.strip(), 'error')
                    result = False

        if result:
            h.log_if_changed(nbhd, 'prohibited_tools', prohibited_tools,
                             'update neighborhood prohibited tools')

        anchored_tools = kw.get('anchored_tools', '')
        validate_tools = dict()
        result = True
        if anchored_tools.strip() != '':
            try:
                validate_tools = {
                    tool.split(':')[0].lower(): tool.split(':')[1]
                    for tool in anchored_tools.replace(' ', '').split(',')}
            except Exception:
                flash('Anchored tools "%s" is invalid' %
                      anchored_tools, 'error')
                result = False

        for tool in validate_tools.keys():
            if tool not in g.entry_points['tool']:
                flash('Anchored tools "%s" is invalid' %
                      anchored_tools, 'error')
                result = False
        if result:
            h.log_if_changed(nbhd, 'anchored_tools', anchored_tools,
                             'update neighborhood anchored tools')

        if icon is not None and icon != b'':
            if self.neighborhood.icon:
                self.neighborhood.icon.delete()
                M.ProjectFile.query.remove(dict(project_id=c.project._id, category={'$regex': r'^icon'}))
            save_icon = c.project.save_icon(icon.filename, icon.file, content_type=icon.type)
            if save_icon:
                M.AuditLog.log('update neighborhood icon')
            else:
                M.AuditLog.log('could not update neighborhood icon')
                flash("There's a problem with the uploaded image", 'error')
        redirect('overview')

    @expose('jinja:allura:templates/neighborhood_help.html')
    @with_trailing_slash
    def help(self, **kw):
        require_access(self.neighborhood, 'admin')
        set_nav(self.neighborhood)
        return dict(
            neighborhood=self.neighborhood,
        )


class NeighborhoodStatsController:

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

    @with_trailing_slash
    @expose('jinja:allura:templates/neighborhood_stats.html')
    def index(self, **kw):
        delete_count = M.Project.query.find(
            dict(neighborhood_id=self.neighborhood._id, deleted=True)).count()
        public_count = 0
        private_count = 0
        last_updated_30 = 0
        last_updated_60 = 0
        last_updated_90 = 0
        today_date = datetime.today()
        # arbitrary limit for efficiency
        if M.Project.query.find(dict(neighborhood_id=self.neighborhood._id, deleted=False)).count() < 20000:
            for p in M.Project.query.find(dict(neighborhood_id=self.neighborhood._id, deleted=False)):
                if p.private:
                    private_count = private_count + 1
                else:
                    public_count = public_count + 1
                    if today_date - p.last_updated < timedelta(days=30):
                        last_updated_30 = last_updated_30 + 1
                    if today_date - p.last_updated < timedelta(days=60):
                        last_updated_60 = last_updated_60 + 1
                    if today_date - p.last_updated < timedelta(days=90):
                        last_updated_90 = last_updated_90 + 1

        set_nav(self.neighborhood)
        return dict(
            delete_count=delete_count,
            public_count=public_count,
            private_count=private_count,
            last_updated_30=last_updated_30,
            last_updated_60=last_updated_60,
            last_updated_90=last_updated_90,
            neighborhood=self.neighborhood,
        )

    @without_trailing_slash
    @expose('jinja:allura:templates/neighborhood_stats_adminlist.html')
    def adminlist(self, sort='alpha', limit=25, page=0, **kw):
        limit, page, start = g.handle_paging(limit, page)

        pq = M.Project.query.find(
            dict(neighborhood_id=self.neighborhood._id, deleted=False))
        if sort == 'alpha':
            pq.sort('name')
        else:
            pq.sort('last_updated', pymongo.DESCENDING)
        count = pq.count()
        projects = pq.skip(start).limit(int(limit)).all()

        entries = []
        for proj in projects:
            admin_role = M.ProjectRole.query.get(
                project_id=proj.root_project._id, name='Admin')
            if admin_role is None:
                continue
            user_role_list = M.ProjectRole.query.find(
                dict(project_id=proj.root_project._id, name=None)).all()
            for ur in user_role_list:
                if ur.user is not None and admin_role._id in ur.roles:
                    entries.append({'project': proj, 'user': ur.user})

        set_nav(self.neighborhood)
        return dict(entries=entries,
                    sort=sort,
                    limit=limit, page=page, count=count,
                    page_list=W.page_list,
                    neighborhood=self.neighborhood,
                    )


class NeighborhoodModerateController:

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

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

    @expose('jinja:allura:templates/neighborhood_moderate.html')
    def index(self, **kw):
        c.project = self.neighborhood.neighborhood_project
        other_nbhds = list(M.Neighborhood.query.find(
            dict(_id={'$ne': self.neighborhood._id})).sort('name'))
        return dict(neighborhood=self.neighborhood,
                    neighborhoods=other_nbhds)

    @expose()
    @require_post()
    def invite(self, pid, neighborhood_id, invite=None, uninvite=None):
        p = M.Project.query.get(shortname=pid, deleted=False,
                                neighborhood_id=ObjectId(neighborhood_id))
        if p is None:
            flash("Can't find %s" % pid, 'error')
            redirect('.')
        if p.neighborhood == self.neighborhood:
            flash("%s is already in the neighborhood" % pid, 'error')
            redirect('.')
        if invite:
            if self.neighborhood._id in p.neighborhood_invitations:
                flash("%s is already invited" % pid, 'warning')
                redirect('.')
            p.neighborhood_invitations.append(self.neighborhood._id)
            flash('%s invited' % pid)
        elif uninvite:
            if self.neighborhood._id not in p.neighborhood_invitations:
                flash("%s is already uninvited" % pid, 'warning')
                redirect('.')
            p.neighborhood_invitations.remove(self.neighborhood._id)
            flash('%s uninvited' % pid)
        redirect('.')

    @expose()
    @require_post()
    def evict(self, pid):
        p = M.Project.query.get(
            shortname=pid, neighborhood_id=self.neighborhood._id, deleted=False)
        if p is None:
            flash("Cannot evict  %s; it's not in the neighborhood"
                  % pid, 'error')
            redirect('.')
        if not p.is_root:
            flash("Cannot evict %s; it's a subproject" % pid, 'error')
            redirect('.')
        n = M.Neighborhood.query.get(name='Projects')
        p.neighborhood_id = n._id
        if self.neighborhood._id in p.neighborhood_invitations:
            p.neighborhood_invitations.remove(self.neighborhood._id)
        flash('%s evicted to Projects' % pid)
        redirect('.')


class NeighborhoodAwardsController:

    def __init__(self, neighborhood=None):
        if neighborhood is not None:
            self.neighborhood = neighborhood

    @expose('jinja:allura:templates/awards.html')
    def index(self, **kw):
        require_access(self.neighborhood, 'admin')
        awards = M.Award.query.find(
            dict(created_by_neighborhood_id=self.neighborhood._id)).all()
        return dict(awards=awards or [], count=len(awards))

    @expose('jinja:allura:templates/award_not_found.html')
    def not_found(self, **kw):
        return dict()

    @expose('jinja:allura:templates/grants.html')
    def grants(self, **kw):
        require_access(self.neighborhood, 'admin')
        grants = M.AwardGrant.query.find(
            dict(granted_by_neighborhood_id=self.neighborhood._id))
        count = grants.count()
        return dict(grants=grants or [], count=count)

    @expose()
    def _lookup(self, award_id, *remainder):
        return AwardController(self.neighborhood, award_id), remainder

    @expose()
    @require_post()
    def create(self, icon=None, short=None, full=None):
        require_access(self.neighborhood, 'admin')
        app_config_id = ObjectId()
        if short:
            award = M.Award(app_config_id=app_config_id)
            award.short = short
            award.full = full
            award.created_by_neighborhood_id = self.neighborhood._id
            if hasattr(icon, 'filename'):
                M.AwardFile.save_image(
                    icon.filename, icon.file, content_type=icon.type,
                    square=True, thumbnail_size=(48, 48),
                    thumbnail_meta=dict(award_id=award._id))
        redirect(six.ensure_text(request.referer or '/'))

    @expose()
    @require_post()
    def grant(self, grant=None, recipient=None, url=None, comment=None):
        require_access(self.neighborhood, 'admin')
        grant_q = M.Award.query.find(dict(short=grant,
                                          created_by_neighborhood_id=self.neighborhood._id)).first()
        recipient_q = M.Project.query.find(dict(
            neighborhood_id=self.neighborhood._id, shortname=recipient,
            deleted=False)).first()
        if grant_q and recipient_q:
            app_config_id = ObjectId()
            award = M.AwardGrant(app_config_id=app_config_id)
            award.award_id = grant_q._id
            award.granted_to_project_id = recipient_q._id
            award.granted_by_neighborhood_id = self.neighborhood._id
            award.award_url = url
            award.comment = comment
            with h.push_context(recipient_q._id):
                g.post_event('project_updated')
        redirect(six.ensure_text(request.referer or '/'))


class AwardController:

    def __init__(self, neighborhood=None, award_id=None):
        self.neighborhood = neighborhood
        if award_id:
            self.award = M.Award.query.find(dict(_id=ObjectId(award_id),
                                                 created_by_neighborhood_id=self.neighborhood._id)).first()

    @with_trailing_slash
    @expose('jinja:allura:templates/award.html')
    def index(self, **kw):
        require_access(self.neighborhood, 'admin')
        set_nav(self.neighborhood)
        if self.award is not None:
            return dict(award=self.award, neighborhood=self.neighborhood)
        else:
            redirect('not_found')

    @expose('jinja:allura:templates/award_not_found.html')
    def not_found(self, **kw):
        return dict()

    @expose()
    def _lookup(self, recipient, *remainder):
        recipient = unquote(recipient)
        return GrantController(self.neighborhood, self.award, recipient), remainder

    @expose()
    def icon(self, **kw):
        icon = self.award.icon
        if not icon:
            raise exc.HTTPNotFound
        return icon.serve()

    @expose()
    @require_post()
    def update(self, icon=None, short=None, full=None):
        require_access(self.neighborhood, 'admin')
        self.award.short = short
        self.award.full = full
        if hasattr(icon, 'filename'):
            if self.award.icon:
                self.award.icon.delete()
            M.AwardFile.save_image(
                icon.filename, icon.file, content_type=icon.type,
                square=True, thumbnail_size=(48, 48),
                thumbnail_meta=dict(award_id=self.award._id))
        for grant in M.AwardGrant.query.find(dict(award_id=self.award._id)):
            with h.push_context(grant.granted_to_project_id):
                g.post_event('project_updated')
        flash('Award updated.')
        redirect(self.award.longurl())

    @expose()
    @require_post()
    def delete(self):
        require_access(self.neighborhood, 'admin')
        if self.award:
            grants = M.AwardGrant.query.find(dict(award_id=self.award._id))
            for grant in grants:
                grant.delete()
                with h.push_context(grant.granted_to_project_id):
                    g.post_event('project_updated')
            M.AwardFile.query.remove(dict(award_id=self.award._id))
            self.award.delete()
        redirect(six.ensure_text(request.referer or '/'))


class GrantController:

    def __init__(self, neighborhood=None, award=None, recipient=None):
        self.neighborhood = neighborhood
        if recipient is not None and award is not None:
            self.recipient = recipient.replace('_', '/')
            self.award = M.Award.query.get(_id=award._id)
            self.project = M.Project.query.find(dict(shortname=self.recipient,
                                                     neighborhood_id=self.neighborhood._id)).first()
            self.grant = M.AwardGrant.query.get(award_id=self.award._id,
                                                granted_to_project_id=self.project._id)

    @with_trailing_slash
    @expose('jinja:allura:templates/grant.html')
    def index(self, **kw):
        require_access(self.neighborhood, 'admin')
        if self.grant is not None:
            return dict(grant=self.grant)
        else:
            redirect('not_found')

    @expose('jinja:allura:templates/award_not_found.html')
    def not_found(self, **kw):
        return dict()

    @expose()
    def icon(self, **kw):
        icon = self.award.icon
        if not icon:
            raise exc.HTTPNotFound
        return icon.serve()

    @expose()
    @require_post()
    def revoke(self):
        require_access(self.neighborhood, 'admin')
        self.grant.delete()
        with h.push_context(self.project._id):
            g.post_event('project_updated')
        redirect(six.ensure_text(request.referer or '/'))


class ProjectImporterController:

    def __init__(self, neighborhood, *a, **kw):
        super().__init__(*a, **kw)
        self.neighborhood = neighborhood

    @expose()
    def _lookup(self, source=None, *rest):
        if source is None:
            raise exc.HTTPNotFound

        # iter_entry_points is a generator with 0 or 1 items, so a loop is the easiest way to handle
        for ep in iter_entry_points('allura.project_importers', source):
            return ep.load()(self.neighborhood), rest

        raise exc.HTTPNotFound


def get_default_wiki_page():
    """
    Gets the default home page from the default Wiki setup.
    """

    from forgewiki import model as WM
    wiki_page = None
    wiki_app = c.project.app_instance('wiki')
    if wiki_app:
        wiki_page = WM.Page.query.get(app_config_id=wiki_app.config._id, title='Home')
        return wiki_page
