#       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 logging
from urllib import quote

from pylons import tmpl_context as c, app_globals as g
from pylons import request
from tg import expose, redirect, flash, validate
from tg.decorators import with_trailing_slash, without_trailing_slash
from bson import ObjectId

from ming.utils import LazyProperty

import allura.tasks
from allura import version
from allura.lib import helpers as h
from allura import model as M
from allura.lib import security
from allura.lib.decorators import require_post
from allura.lib.security import has_access
from allura.lib import validators as v
from allura.app import Application, SitemapEntry, DefaultAdminController, ConfigOption

log = logging.getLogger(__name__)


class RepositoryApp(Application):
    END_OF_REF_ESCAPE = '~'
    __version__ = version.__version__
    permissions = [
        'read', 'write', 'create',
        'unmoderated_post', 'post', 'moderate', 'admin',
        'configure']
    permissions_desc = {
        'read': 'Browse repo via web UI. Removing read does not prevent direct repo read access.',
        'write': 'Repo push access.',
        'create': 'Not used.',
        'admin': 'Set permissions, default branch, and viewable files.',
    }
    config_options = Application.config_options + [
        ConfigOption('cloned_from_project_id', ObjectId, None),
        ConfigOption('cloned_from_repo_id', ObjectId, None),
        ConfigOption('init_from_url', str, None),
        ConfigOption('external_checkout_url', str, None)
    ]
    tool_label = 'Repository'
    default_mount_label = 'Code'
    default_mount_point = 'code'
    relaxed_mount_points = True
    ordinal = 2
    forkable = False
    default_branch_name = None  # master or default or some such
    repo = None  # override with a property in child class
    icons = {
        24: 'images/code_24.png',
        32: 'images/code_32.png',
        48: 'images/code_48.png'
    }

    def __init__(self, project, config):
        Application.__init__(self, project, config)
        self.admin = RepoAdminController(self)

    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()]]

    def admin_menu(self):
        admin_url = c.project.url() + 'admin/' + \
            self.config.options.mount_point + '/'
        links = [
            SitemapEntry(
                'Checkout URL',
                c.project.url() + 'admin/' +
                self.config.options.mount_point +
                '/' + 'checkout_url',
                className='admin_modal'),
            SitemapEntry(
                'Viewable Files',
                admin_url + 'extensions',
                className='admin_modal'),
            SitemapEntry(
                'Refresh Repository',
                c.project.url() +
                self.config.options.mount_point +
                '/refresh'),
        ]
        links += super(RepositoryApp, self).admin_menu()
        [links.remove(l) for l in links[:] if l.label == 'Options']
        return links

    @h.exceptionless([], log)
    def sidebar_menu(self):
        if not self.repo or self.repo.status != 'ready':
            return []
        links = [SitemapEntry('Browse Commits', c.app.url +
                              'commit_browser', ui_icon=g.icons['folder'])]
        if self.forkable and self.repo.status == 'ready' and not self.repo.is_empty():
            links.append(
                SitemapEntry('Fork', c.app.url + 'fork', ui_icon=g.icons['fork']))
        merge_request_count = self.repo.merge_requests_by_statuses(
            'open').count()
        if merge_request_count:
            links += [
                SitemapEntry(
                    'Merge Requests', c.app.url + 'merge-requests/',
                    small=merge_request_count)]
        if self.repo.forks:
            links += [
                SitemapEntry('Forks', c.app.url + 'forks/',
                             small=len(self.repo.forks))
            ]
        if self.repo.upstream_repo.name:
            repo_path_parts = self.repo.upstream_repo.name.strip(
                '/').split('/')
            links += [
                SitemapEntry('Clone of'),
                SitemapEntry('%s / %s' %
                             (repo_path_parts[1], repo_path_parts[-1]),
                             self.repo.upstream_repo.name)
            ]
            if not c.app.repo.is_empty() and has_access(c.app.repo, 'admin'):
                merge_url = c.app.url + 'request_merge'
                if getattr(c, 'revision', None):
                    merge_url = merge_url + '?branch=' + h.urlquote(c.revision)
                links.append(SitemapEntry('Request Merge', merge_url,
                             ui_icon=g.icons['merge'],
                                          ))
            pending_upstream_merges = self.repo.pending_upstream_merges()
            if pending_upstream_merges:
                links.append(SitemapEntry(
                    'Pending Merges',
                    self.repo.upstream_repo.name + 'merge-requests/',
                    small=pending_upstream_merges))
        ref_url = self.repo.url_for_commit(
            self.default_branch_name, url_type='ref')
        branches = self.repo.get_branches()
        if branches:
            links.append(SitemapEntry('Branches'))
            for branch in branches:
                if branch.name == self.default_branch_name:
                    branches.remove(branch)
                    branches.insert(0, branch)
                    break
            max_branches = 10
            for branch in branches[:max_branches]:
                links.append(SitemapEntry(
                    branch.name,
                    quote(self.repo.url_for_commit(branch.name) + 'tree/')))
            if len(branches) > max_branches:
                links.append(
                    SitemapEntry(
                        'More Branches',
                        ref_url + 'branches/',
                    ))
        tags = self.repo.get_tags()
        if tags:
            links.append(SitemapEntry('Tags'))
            max_tags = 10
            for b in tags[:max_tags]:
                links.append(SitemapEntry(
                    b.name,
                    quote(self.repo.url_for_commit(b.name) + 'tree/')))
            if len(tags) > max_tags:
                links.append(
                    SitemapEntry(
                        'More Tags',
                        ref_url + 'tags/',
                    ))
        return links

    def install(self, project):
        self.config.options['project_name'] = project.name
        super(RepositoryApp, self).install(project)
        role_admin = M.ProjectRole.by_name('Admin')._id
        role_developer = M.ProjectRole.by_name('Developer')._id
        role_auth = M.ProjectRole.authenticated()._id
        role_anon = M.ProjectRole.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, 'create'),
            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):
        allura.tasks.repo_tasks.uninstall.post()


class RepoAdminController(DefaultAdminController):

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

    @LazyProperty
    def repo(self):
        return self.app.repo

    def _check_security(self):
        security.require_access(self.app, 'configure')

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

    @without_trailing_slash
    @expose('jinja:allura:templates/repo/admin_extensions.html')
    def extensions(self, **kw):
        return dict(app=self.app,
                    allow_config=True,
                    additional_viewable_extensions=getattr(self.repo, 'additional_viewable_extensions', ''))

    @without_trailing_slash
    @expose()
    @require_post()
    def set_extensions(self, **post_data):
        self.repo.additional_viewable_extensions = post_data[
            'additional_viewable_extensions']

    @without_trailing_slash
    @expose('jinja:allura:templates/repo/default_branch.html')
    def set_default_branch_name(self, branch_name=None, **kw):
        if (request.method == 'POST') and branch_name:
            self.repo.set_default_branch(branch_name)
            redirect(request.referer)
        else:
            return dict(app=self.app,
                        default_branch_name=self.app.default_branch_name)

    @without_trailing_slash
    @expose('jinja:allura:templates/repo/checkout_url.html')
    def checkout_url(self):
        return dict(app=self.app)

    @without_trailing_slash
    @expose()
    @require_post()
    @validate({'external_checkout_url': v.NonHttpUrl})
    def set_checkout_url(self, **post_data):
        external_checkout_url = (post_data.get('external_checkout_url') or '').strip()
        if 'external_checkout_url' not in c.form_errors:
            if (self.app.config.options.get('external_checkout_url') or '') != external_checkout_url:
                self.app.config.options.external_checkout_url = external_checkout_url
                flash("External checkout URL successfully changed")
        else:
            flash("Invalid external checkout URL: %s" % c.form_errors['external_checkout_url'], "error")
        redirect(c.project.url() + 'admin/tools')
