#       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
from pylons import tmpl_context as c
import formencode
from formencode import validators
from webob import exc
from datetime import datetime

from allura.app import Application, SitemapEntry
from allura.lib import helpers as h
from allura.lib.security import has_access
from allura import model as M
from allura.eventslistener import EventsListener
from model.stats import UserStats
from controllers.userstats import ForgeUserStatsController

from forgeuserstats import version
from forgeuserstats.controllers.userstats import ForgeUserStatsController

from ming.orm import session

log = logging.getLogger(__name__)

class UserStatsListener(EventsListener):
    def newArtifact(self, art_type, art_datetime, project, user):
        stats = user.stats
        if not stats:
            stats = UserStats.create(user)
        stats.addNewArtifact(art_type, art_datetime, project)

    def modifiedArtifact(self, art_type, art_datetime, project, user):
        stats = user.stats
        if not stats:
            stats = UserStats.create(user)

        stats.addModifiedArtifact(art_type, art_datetime, project)

    def newUser(self, user):
        stats = UserStats.create(user)

    def ticketEvent(self, event_type, ticket, project, user):
        if user is None:
            return
        stats = user.stats
        if not stats:
            stats = UserStats.create(user)

        if event_type == "assigned":
            stats.addAssignedTicket(ticket.mod_date, project)
        elif event_type == "revoked":
            stats.addRevokedTicket(ticket.mod_date, project)
        elif event_type == "closed":
            stats.addClosedTicket(ticket.created_date,ticket.mod_date,project)

    def newCommit(self, newcommit, project, user):
        stats = user.stats
        if not stats:
            stats = UserStats.create(user)

        stats.addCommit(newcommit, datetime.utcnow(), project)

    def addUserLogin(self, user):
        stats = user.stats
        if not stats:
            stats = UserStats.create(user)

        stats.addLogin(datetime.utcnow())

    def newOrganization(self, organization):
        pass

class ForgeUserStatsApp(Application):
    __version__ = version.__version__
    tool_label='UserStats'
    default_mount_label='Stats'
    default_mount_point='stats'
    permissions = ['configure', 'read', 'write',
                    'unmoderated_post', 'post', 'moderate', 'admin']
    permissions_desc = {
        'read': 'View user stats.',
        'admin': 'Toggle stats visibility.',
    }
    ordinal=15
    installable=False
    config_options = Application.config_options
    default_external_feeds = []
    icons={
        24:'../../tool/userstats/images/stats_24.png',
        32:'../../tool/userstats/images/stats_32.png',
        48:'../../tool/userstats/images/stats_48.png'
    }
    root = ForgeUserStatsController()

    def __init__(self, project, config):
        Application.__init__(self, project, config)
        role_admin = M.ProjectRole.by_name('Admin', project)._id
        role_anon = M.ProjectRole.by_name('*anonymous', project)._id
        self.config.acl = [
            M.ACE.allow(role_anon, 'read'),
            M.ACE.allow(role_admin, 'admin')]

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

    def is_visible_to(self, user):
        # we don't work with user subprojects
        return c.project.is_root

    @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

    @h.exceptionless([], log)
    def sidebar_menu(self):
        base = c.app.url
        links = [SitemapEntry('Overview', base),
                 SitemapEntry('Commits', base + 'commits'),
                 SitemapEntry('Artifacts', base + 'artifacts'),
                 SitemapEntry('Tickets', base + 'tickets')]
        return links

    def admin_menu(self):
        links = [SitemapEntry(
                     'Settings', c.project.url() + 'userstats/settings')]
        return links

    def install(self, project):
        #It doesn't make any sense to install the tool twice on the same
        #project therefore, if it already exists, it doesn't install it
        #a second time.
        for tool in project.app_configs:
            if tool.tool_name == 'userstats':
                if self.config.options.mount_point!=tool.options.mount_point:
                    project.uninstall_app(self.config.options.mount_point)
                    return

    def uninstall(self, project):
        self.config.delete()
        session(self.config).flush()
