#       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
import urllib
import json
import difflib
from datetime import datetime, timedelta
from bson import ObjectId
import os

import pymongo
from pymongo.errors import OperationFailure
from pylons import tmpl_context as c, app_globals as g
from pprint import pformat
from paste.deploy.converters import aslist, asbool
import jinja2

from ming import schema
from ming.utils import LazyProperty
from ming.orm import Mapper, session
from ming.orm import FieldProperty, ForeignIdProperty, RelationProperty
from ming.orm.declarative import MappedClass
from ming.orm.ormsession import ThreadLocalORMSession

from tg import config as tg_config

from allura.model import (
    ACE,
    DENY_ALL,

    AppConfig,
    Artifact,
    BaseAttachment,
    Feed,
    Mailbox,
    MovedArtifact,
    Notification,
    ProjectRole,
    Snapshot,
    Thread,
    User,
    VersionedArtifact,
    VotableArtifact,

    artifact_orm_session,
    project_orm_session,
    AlluraUserProperty,
    Shortlink
)
from allura.model.timeline import ActivityObject
from allura.model.notification import MailFooter
from allura.model.types import MarkdownCache, EVERYONE

from allura.lib import security
from allura.lib.search import search_artifact, SearchError
from allura.lib import utils
from allura.lib import helpers as h
from allura.lib.plugin import ImportIdConverter
from allura.lib.security import require_access
from allura.tasks import mail_tasks
from forgetracker import search as tsearch


log = logging.getLogger(__name__)

CUSTOM_FIELD_SOLR_TYPES = dict(boolean='_b', number='_d')
SOLR_TYPE_DEFAULTS = dict(_b=False, _d=0)


def get_default_for_solr_type(solr_type):
    return SOLR_TYPE_DEFAULTS.get(solr_type, u'')

config = utils.ConfigProxy(
    common_suffix='forgemail.domain',
    new_solr='solr.use_new_types')


class Globals(MappedClass):

    class __mongometa__:
        name = 'globals'
        session = project_orm_session
        indexes = ['app_config_id']

    type_s = 'Globals'
    _id = FieldProperty(schema.ObjectId)
    app_config_id = ForeignIdProperty(
        AppConfig, if_missing=lambda: c.app.config._id)
    app_config = RelationProperty(AppConfig, via='app_config_id')
    last_ticket_num = FieldProperty(int)
    status_names = FieldProperty(str)
    open_status_names = FieldProperty(str)
    closed_status_names = FieldProperty(str)
    milestone_names = FieldProperty(str, if_missing='')
    custom_fields = FieldProperty([{str: None}])
    _bin_counts = FieldProperty(schema.Deprecated)  # {str:int})
    _bin_counts_data = FieldProperty([dict(summary=str, hits=int)])
    _bin_counts_expire = FieldProperty(datetime)
    _bin_counts_invalidated = FieldProperty(datetime)
    # [dict(name=str,hits=int,closed=int)])
    _milestone_counts = FieldProperty(schema.Deprecated)
    _milestone_counts_expire = FieldProperty(schema.Deprecated)  # datetime)
    show_in_search = FieldProperty({str: bool}, if_missing={'ticket_num': True,
                                                            'summary': True,
                                                            '_milestone': True,
                                                            'status': True,
                                                            'assigned_to': True,
                                                            'reported_by': False,
                                                            'created_date': True,
                                                            'mod_date': True,
                                                            'labels': False,
                                                            })

    def next_ticket_num(self):
        gbl = Globals.query.find_and_modify(
            query=dict(app_config_id=self.app_config_id),
            update={'$inc': {'last_ticket_num': 1}},
            new=True)
        session(gbl).expunge(gbl)
        return gbl.last_ticket_num

    @property
    def all_status_names(self):
        return ' '.join([self.open_status_names, self.closed_status_names])

    @property
    def set_of_all_status_names(self):
        return set([name for name in self.all_status_names.split(' ') if name])

    @property
    def set_of_open_status_names(self):
        return set([name for name in self.open_status_names.split(' ') if name])

    @property
    def set_of_closed_status_names(self):
        return set([name for name in self.closed_status_names.split(' ') if name])

    @property
    def not_closed_query(self):
        return ' && '.join(['!status:' + name for name in self.set_of_closed_status_names])

    @property
    def not_closed_mongo_query(self):
        return dict(
            status={'$nin': list(self.set_of_closed_status_names)})

    @property
    def closed_query(self):
        return ' or '.join(['status:' + name for name in self.set_of_closed_status_names])

    @property
    def milestone_fields(self):
        return [fld for fld in self.custom_fields if fld['type'] == 'milestone']

    def get_custom_field(self, name):
        for fld in self.custom_fields:
            if fld['name'] == name:
                return fld
        return None

    def get_custom_field_solr_type(self, field_name):
        """Return the Solr type for a custom field.

        :param field_name: Name of the custom field
        :type field_name: str
        :returns: The Solr type suffix (e.g. '_s', '_i', '_b') or None if
            there is no custom_field named ``field_name``.

        """
        fld = self.get_custom_field(field_name)
        if fld:
            return CUSTOM_FIELD_SOLR_TYPES.get(fld.type, '_s')
        return None

    def update_bin_counts(self):
        # Refresh bin counts
        self._bin_counts_data = []
        for b in Bin.query.find(dict(
                app_config_id=self.app_config_id)):
            if b.terms and '$USER' in b.terms:
                # skip queries with $USER variable, hits will be inconsistent
                # for them
                continue
            r = search_artifact(Ticket, b.terms, rows=0, short_timeout=False, fq=['-deleted_b:true'])
            hits = r is not None and r.hits or 0
            self._bin_counts_data.append(dict(summary=b.summary, hits=hits))
        self._bin_counts_expire = \
            datetime.utcnow() + timedelta(minutes=60)
        self._bin_counts_invalidated = None

    def bin_count(self, name):
        # not sure why we expire bin counts after an hour even if unchanged
        # I guess a catch-all in case invalidate_bin_counts is missed
        if self._bin_counts_expire < datetime.utcnow():
            self.invalidate_bin_counts()
        for d in self._bin_counts_data:
            if d['summary'] == name:
                return d
        return dict(summary=name, hits=0)

    def milestone_count(self, name):
        fld_name, m_name = name.split(':', 1)
        d = dict(name=name, hits=0, closed=0)
        if not (fld_name and m_name):
            return d
        mongo_query = {
            'custom_fields.%s' % fld_name: m_name,
            'app_config_id': self.app_config_id,
            'deleted': False
        }
        d['hits'] = Ticket.query.find(dict(mongo_query, acl=[])).count()
        d['closed'] = Ticket.query.find(dict(mongo_query, acl=[],
                                             status={'$in': list(self.set_of_closed_status_names)})).count()

        secured_tickets = Ticket.query.find(dict(mongo_query, acl={"$ne": []}))
        if secured_tickets.count():
            tickets = [t for t in secured_tickets if security.has_access(t, 'read')]
            d['hits'] += len(tickets)
            d['closed'] += sum(1 for t in tickets if t.status in self.set_of_closed_status_names)
        return d

    def invalidate_bin_counts(self):
        '''Force expiry of bin counts and queue them to be updated.'''
        # To prevent multiple calls to this method from piling on redundant
        # tasks, we set _bin_counts_invalidated when we post the task, and
        # the task clears it when it's done.  However, in the off chance
        # that the task fails or is interrupted, we ignore the flag if it's
        # older than 5 minutes.
        delay = int(tg_config.get('forgetracker.bin_invalidate_delay', 5))
        invalidation_expiry = datetime.utcnow() - timedelta(minutes=delay)
        if self._bin_counts_invalidated is not None and \
           self._bin_counts_invalidated > invalidation_expiry:
            return
        self._bin_counts_invalidated = datetime.utcnow()
        from forgetracker import tasks  # prevent circular import
        tasks.update_bin_counts.post(self.app_config_id, delay=delay)

    def sortable_custom_fields_shown_in_search(self):
        def solr_type(field_name):
            # Pre solr-4.2.1 code indexed all custom fields as strings, so
            # they must be searched as such.
            if not config.get_bool('new_solr'):
                return '_s'
            return self.get_custom_field_solr_type(field_name) or '_s'

        return [dict(
            sortable_name='{0}{1}'.format(field['name'],
                solr_type(field['name'])),
            name=field['name'],
            label=field['label'])
            for field in self.custom_fields
            if field.get('show_in_search')]

    def has_deleted_tickets(self):
        return Ticket.query.find(dict(
            app_config_id=self.app_config_id, deleted=True)).count() > 0

    def move_tickets(self, ticket_ids, destination_tracker_id):
        tracker = AppConfig.query.get(_id=destination_tracker_id)
        tickets = Ticket.query.find(dict(
            _id={'$in': [ObjectId(id) for id in ticket_ids]},
            app_config_id=self.app_config_id)).sort('ticket_num').all()
        filtered = self.filtered_by_subscription({t._id: t for t in tickets})
        original_ticket_nums = {t._id: t.ticket_num for t in tickets}
        users = User.query.find({'_id': {'$in': filtered.keys()}}).all()
        moved_tickets = {}
        for ticket in tickets:
            moved = ticket.move(tracker, notify=False)
            moved_tickets[moved._id] = moved
        mail = dict(
            sender=c.project.app_instance(self.app_config).email_address,
            fromaddr=str(c.user.email_address_header()),
            reply_to=str(c.user.email_address_header()),
            subject='[%s:%s] Mass ticket moving by %s' % (c.project.shortname,
                                                          self.app_config.options.mount_point,
                                                          c.user.display_name))
        tmpl = g.jinja2_env.get_template(
            'forgetracker:data/mass_move_report.html')

        tmpl_context = {
            'original_tracker': '%s:%s' % (c.project.shortname,
                                           self.app_config.options.mount_point),
            'destination_tracker': '%s:%s' % (tracker.project.shortname,
                                              tracker.options.mount_point),
            'tickets': [],
        }
        for user in users:
            tmpl_context['tickets'] = ({
                'original_num': original_ticket_nums[_id],
                'destination_num': moved_tickets[_id].ticket_num,
                'summary': moved_tickets[_id].summary
            } for _id in filtered.get(user._id, []))
            mail.update(dict(
                message_id=h.gen_message_id(),
                text=tmpl.render(tmpl_context),
                destinations=[str(user._id)]))
            mail_tasks.sendmail.post(**mail)

        if self.app_config.options.get('TicketMonitoringType') in (
                'AllTicketChanges', 'AllPublicTicketChanges'):
            monitoring_email = self.app_config.options.get(
                'TicketMonitoringEmail')
            tmpl_context['tickets'] = [{
                'original_num': original_ticket_nums[_id],
                'destination_num': moved_tickets[_id].ticket_num,
                'summary': moved_tickets[_id].summary
            } for _id, t in moved_tickets.iteritems()
                if (not t.private or
                    self.app_config.options.get('TicketMonitoringType') ==
                    'AllTicketChanges')]
            if len(tmpl_context['tickets']) > 0:
                mail.update(dict(
                    message_id=h.gen_message_id(),
                    text=tmpl.render(tmpl_context),
                    destinations=[monitoring_email]))
                mail_tasks.sendmail.post(**mail)

        moved_from = '%s/%s' % (c.project.shortname,
                                self.app_config.options.mount_point)
        moved_to = '%s/%s' % (tracker.project.shortname,
                              tracker.options.mount_point)
        text = 'Tickets moved from %s to %s' % (moved_from, moved_to)
        Notification.post_user(c.user, None, 'flash', text=text)

    def update_tickets(self, **post_data):
        from forgetracker.tracker_main import get_change_text, get_label
        tickets = Ticket.query.find(dict(
            _id={'$in': [ObjectId(id)
                         for id in aslist(
                             post_data['__ticket_ids'])]},
            app_config_id=self.app_config_id)).all()

        fields = set(['status', 'private'])
        values = {}
        labels = post_data.get('labels', [])

        for k in fields:
            v = post_data.get(k)
            if v:
                values[k] = v
        assigned_to = post_data.get('assigned_to')
        if assigned_to == '-':
            values['assigned_to_id'] = None
        elif assigned_to:
            user = c.project.user_in_project(assigned_to)
            if user:
                values['assigned_to_id'] = user._id
        private = post_data.get('private')
        if private:
            values['private'] = asbool(private)

        deleted = post_data.get('deleted')
        if deleted:
            values['deleted'] = asbool(deleted)

        discussion_disabled = post_data.get('discussion_disabled')
        if discussion_disabled:
            values['disabled_discussion'] = asbool(discussion_disabled)

        custom_values = {}
        custom_fields = {}
        for cf in self.custom_fields or []:
            v = post_data.get(cf.name)
            if v:
                custom_values[cf.name] = v
                custom_fields[cf.name] = cf

        changes = {}
        changed_tickets = {}
        for ticket in tickets:
            message = ''
            if labels:
                values['labels'] = self.append_new_labels(
                    ticket.labels, labels.split(','))
            for k, v in sorted(values.iteritems()):
                if k == 'deleted':
                    if v:
                        ticket.soft_delete()
                        break
                elif k == 'assigned_to_id':
                    new_user = User.query.get(_id=v)
                    old_user = User.query.get(_id=getattr(ticket, k))
                    if new_user:
                        message += get_change_text(
                            get_label(k),
                            new_user.display_name,
                            old_user.display_name)
                elif k == 'private' or k == 'discussion_disabled':
                    def _text(val):
                        if val:
                            return 'Yes'
                        else:
                            return 'No'

                    message += get_change_text(
                        get_label(k),
                        _text(v),
                        _text(getattr(ticket, k)))
                else:
                    message += get_change_text(
                        get_label(k),
                        v,
                        getattr(ticket, k))
                setattr(ticket, k, v)
            for k, v in sorted(custom_values.iteritems()):
                def cf_val(cf):
                    return ticket.get_custom_user(cf.name) \
                        if cf.type == 'user' \
                        else ticket.custom_fields.get(cf.name)
                cf = custom_fields[k]
                old_value = cf_val(cf)
                if cf.type == 'boolean':
                    v = asbool(v)
                ticket.custom_fields[k] = v
                new_value = cf_val(cf)
                message += get_change_text(
                    cf.label,
                    new_value,
                    old_value)
            if message != '':
                changes[ticket._id] = message
                changed_tickets[ticket._id] = ticket
                ticket.discussion_thread.post(message, notify=False, is_meta=True)
                ticket.commit()

        filtered_changes = self.filtered_by_subscription(changed_tickets)
        users = User.query.find(
            {'_id': {'$in': filtered_changes.keys()}}).all()

        def changes_iter(user):
            for t_id in filtered_changes.get(user._id, []):
                # mark changes text as safe, thus it wouldn't be escaped in plain-text emails
                # html part of email is handled by markdown and it'll be
                # properly escaped
                yield (changed_tickets[t_id], jinja2.Markup(changes[t_id]))
        mail = dict(
            sender=c.project.app_instance(self.app_config).email_address,
            fromaddr=str(c.user._id),
            reply_to=tg_config['forgemail.return_path'],
            subject='[%s:%s] Mass edit changes by %s' % (c.project.shortname,
                                                         self.app_config.options.mount_point,
                                                         c.user.display_name),
        )
        tmpl = g.jinja2_env.get_template('forgetracker:data/mass_report.html')
        head = []
        for f, v in sorted(values.iteritems()):
            if f == 'assigned_to_id':
                user = User.query.get(_id=v)
                v = user.display_name if user else v
            head.append('- **%s**: %s' % (get_label(f), v))
        for f, v in sorted(custom_values.iteritems()):
            cf = custom_fields[f]
            if cf.type == 'user':
                user = User.by_username(v)
                v = user.display_name if user else v
            head.append('- **%s**: %s' % (cf.label, v))
        tmpl_context = {'context': c, 'data':
                        {'header': jinja2.Markup('\n'.join(['Mass edit changing:', ''] + head))}}
        for user in users:
            tmpl_context['data'].update({'changes': changes_iter(user)})
            mail.update(dict(
                message_id=h.gen_message_id(),
                text=tmpl.render(tmpl_context),
                destinations=[str(user._id)]))
            mail_tasks.sendmail.post(**mail)

        if self.app_config.options.get('TicketMonitoringType') in (
                'AllTicketChanges', 'AllPublicTicketChanges'):
            monitoring_email = self.app_config.options.get(
                'TicketMonitoringEmail')
            visible_changes = []
            for t_id, t in changed_tickets.items():
                if (not t.private or
                        self.app_config.options.get('TicketMonitoringType') ==
                        'AllTicketChanges'):
                    visible_changes.append(
                        (changed_tickets[t_id], jinja2.Markup(changes[t_id])))
            if visible_changes:
                tmpl_context['data'].update({'changes': visible_changes})
                mail.update(dict(
                    message_id=h.gen_message_id(),
                    text=tmpl.render(tmpl_context),
                    destinations=[monitoring_email]))
                mail_tasks.sendmail.post(**mail)

        self.invalidate_bin_counts()
        ThreadLocalORMSession.flush_all()
        app = '%s/%s' % (c.project.shortname,
                         self.app_config.options.mount_point)
        count = len(tickets)
        text = 'Updated {} ticket{} in {}'.format(
            count, 's' if count != 1 else '', app)
        Notification.post_user(c.user, None, 'flash', text=text)

    def filtered_by_subscription(self, tickets, project_id=None, app_config_id=None):
        p_id = project_id if project_id else c.project._id
        ac_id = app_config_id if app_config_id else self.app_config_id
        ticket_ids = tickets.keys()
        tickets_index_id = {
            ticket.index_id(): t_id for t_id, ticket in tickets.iteritems()}
        subscriptions = Mailbox.query.find({
            'project_id': p_id,
            'app_config_id': ac_id,
            'artifact_index_id': {'$in': tickets_index_id.keys() + [None]}})
        filtered = {}
        for subscription in subscriptions:
            if subscription.artifact_index_id is None:
                # subscribed to entire tool, will see all changes
                filtered[subscription.user_id] = set(ticket_ids)
            elif subscription.artifact_index_id in tickets_index_id.keys():
                user = filtered.setdefault(subscription.user_id, set())
                user.add(tickets_index_id[subscription.artifact_index_id])
        return filtered

    def append_new_labels(self, old_labels, new_labels):
        old_labels = set(old_labels)
        new_labels = set(l.strip() for l in new_labels)
        return list(old_labels | new_labels)


class TicketHistory(Snapshot):

    class __mongometa__:
        name = 'ticket_history'

    def original(self):
        return Ticket.query.get(_id=self.artifact_id)

    def shorthand_id(self):
        orig = self.original()
        if not orig:
            return None
        return '%s#%s' % (orig.shorthand_id(), self.version)

    def url(self):
        orig = self.original()
        if not orig:
            return None
        return orig.url() + '?version=%d' % self.version

    @property
    def assigned_to(self):
        if self.data.assigned_to_id is None:
            return None
        return User.query.get(_id=self.data.assigned_to_id)

    def index(self):
        orig = self.original()
        if not orig:
            return None
        result = Snapshot.index(self)
        result.update(
            title='Version %d of %s' % (
                self.version, orig.summary),
            type_s='Ticket Snapshot',
            text=self.data.summary)
        # Tracker uses search with default solr parser. It would match only on
        # `text`, so we're appending all other field values into `text`, to match on it too.
        result['text'] += pformat(result.values())
        return result


class Bin(Artifact, ActivityObject):

    class __mongometa__:
        name = 'bin'

    type_s = 'Bin'
    _id = FieldProperty(schema.ObjectId)
    summary = FieldProperty(str, required=True, allow_none=False)
    terms = FieldProperty(str, if_missing='')
    sort = FieldProperty(str, if_missing='')

    @property
    def activity_name(self):
        return 'search bin %s' % self.summary

    def url(self):
        base = self.app_config.url() + 'search/?'
        params = dict(q=(h.really_unicode(self.terms).encode('utf-8') or ''))
        if self.sort:
            params['sort'] = self.sort
        return base + urllib.urlencode(params)

    def shorthand_id(self):
        return self.summary

    def index(self):
        result = Artifact.index(self)
        result.update(
            type_s=self.type_s,
            summary_t=self.summary,
            terms_s=self.terms)
        return result

    def __json__(self):
        return dict(
            _id=self._id,
            summary=self.summary,
            terms=self.terms,
            sort=self.sort,
        )


class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):

    class __mongometa__:
        name = 'ticket'
        history_class = TicketHistory
        indexes = [
            'ticket_num',
            ('app_config_id', 'custom_fields._milestone'),
            'import_id',
        ]
        unique_indexes = [
            ('app_config_id', 'ticket_num'),
        ]

    type_s = 'Ticket'
    _id = FieldProperty(schema.ObjectId)
    created_date = FieldProperty(datetime, if_missing=datetime.utcnow)

    ticket_num = FieldProperty(int, required=True, allow_none=False)
    summary = FieldProperty(str)
    description = FieldProperty(str, if_missing='')
    description_cache = FieldProperty(MarkdownCache)
    reported_by_id = AlluraUserProperty(if_missing=lambda: c.user._id)
    assigned_to_id = AlluraUserProperty(if_missing=None)
    milestone = FieldProperty(str, if_missing='')
    status = FieldProperty(str, if_missing='')
    custom_fields = FieldProperty({str: None})

    reported_by = RelationProperty(User, via='reported_by_id')

    def link_text(self):
        text = super(Ticket, self).link_text()
        if self.is_closed:
            return jinja2.Markup('<s>') + text + jinja2.Markup('</s>')
        return text

    @property
    def activity_name(self):
        return 'ticket #%s' % self.ticket_num

    @property
    def activity_extras(self):
        d = ActivityObject.activity_extras.fget(self)
        d.update(summary=self.summary)
        return d

    @classmethod
    def new(cls):
        '''Create a new ticket, safely (ensuring a unique ticket_num'''
        while True:
            ticket_num = c.app.globals.next_ticket_num()
            ticket = cls(
                app_config_id=c.app.config._id,
                custom_fields=dict(),
                ticket_num=ticket_num)
            try:
                session(ticket).flush(ticket)
                h.log_action(log, 'opened').info('')
                return ticket
            except OperationFailure, err:
                if 'duplicate' in err.args[0]:
                    log.warning('Try to create duplicate ticket %s',
                                ticket.url())
                    session(ticket).expunge(ticket)
                    continue
                raise

    def index(self):
        result = VersionedArtifact.index(self)
        result.update(
            title='Ticket %s' % self.ticket_num,
            version_i=self.version,
            type_s=self.type_s,
            created_date_dt=self.created_date,
            ticket_num_i=self.ticket_num,
            summary_t=self.summary,
            milestone_s=self.milestone,
            status_s=self.status,
            text=self.description,
            snippet_s=self.summary,
            private_b=self.private,
            discussion_disabled_b=self.discussion_disabled,
            votes_up_i=self.votes_up,
            votes_down_i=self.votes_down,
            votes_total_i=(self.votes_up - self.votes_down),
            import_id_s=ImportIdConverter.get().simplify(self.import_id)
        )
        for k, v in self.custom_fields.iteritems():
            # Pre solr-4.2.1 code expects all custom fields to be indexed
            # as strings.
            if not config.get_bool('new_solr'):
                result[k + '_s'] = unicode(v)

            # Now let's also index with proper Solr types.
            solr_type = self.app.globals.get_custom_field_solr_type(k)
            if solr_type:
                result[k + solr_type] = (v or
                                         get_default_for_solr_type(solr_type))

        result['reported_by_s'] = self.reported_by.username if self.reported_by else None
        result['assigned_to_s'] = self.assigned_to.username if self.assigned_to else None

        # Tracker uses search with default solr parser. It would match only on
        # `text`, so we're appending all other field values into `text`, to
        # match on it too.
        result['text'] += pformat(result.values())
        return result

    @classmethod
    def attachment_class(cls):
        return TicketAttachment

    @classmethod
    def translate_query(cls, q, fields):
        q = super(Ticket, cls).translate_query(q, fields)
        cf = [f.name for f in c.app.globals.custom_fields]
        solr_field = '{0}{1}'
        solr_type = '_s'
        for f in cf:
            # Solr 4.2.1 index contains properly typed custom fields, so we
            # can search on those instead of the old string-type solr fields.
            if config.get_bool('new_solr'):
                solr_type = (c.app.globals.get_custom_field_solr_type(f)
                             or solr_type)
            actual = solr_field.format(f, solr_type)
            q = q.replace(f + ':', actual + ':')
        return q

    @property
    def _milestone(self):
        milestone = None
        for fld in self.globals.milestone_fields:
            if fld.name == '_milestone':
                return self.custom_fields.get('_milestone', '')
        return milestone

    @property
    def assigned_to(self):
        if self.assigned_to_id is None:
            return None
        return User.query.get(_id=self.assigned_to_id)

    @property
    def reported_by_username(self):
        if self.reported_by:
            return self.reported_by.username
        return 'nobody'

    @property
    def assigned_to_username(self):
        if self.assigned_to:
            return self.assigned_to.username
        return 'nobody'

    @property
    def email_address(self):
        if self.discussion_disabled:
            return tg_config.get('forgemail.return_path')
        if c.app.config.options.get('AllowEmailPosting', True):
            domain = self.email_domain
            return '%s@%s%s' % (self.ticket_num, domain, config.common_suffix)
        else:
            return tg_config.get('forgemail.return_path')

    @property
    def email_subject(self):
        return '#%s %s' % (self.ticket_num, self.summary)

    @LazyProperty
    def globals(self):
        return Globals.query.get(app_config_id=self.app_config_id)

    @property
    def open_or_closed(self):
        return 'closed' if self.status in self.app.globals.set_of_closed_status_names else 'open'

    @property
    def is_closed(self):
        return self.open_or_closed == 'closed'

    @property
    def monitoring_email(self):
        return self.app_config.options.get('TicketMonitoringEmail')

    @property
    def notify_post(self):
        monitoring_type = self.app_config.options.get('TicketMonitoringType')
        return monitoring_type == 'AllTicketChanges' or (
            monitoring_type == 'AllPublicTicketChanges' and
            not self.private)

    def get_custom_user(self, custom_user_field_name):
        fld = None
        for f in c.app.globals.custom_fields:
            if f.name == custom_user_field_name:
                fld = f
                break
        if not fld:
            raise KeyError, 'Custom field "%s" does not exist.' % custom_user_field_name
        if fld.type != 'user':
            raise TypeError, 'Custom field "%s" is of type "%s"; expected ' \
                             'type "user".' % (
                                 custom_user_field_name, fld.type)
        username = self.custom_fields.get(custom_user_field_name)
        if not username:
            return None
        user = self.app_config.project.user_in_project(username)
        if user == User.anonymous():
            return None
        return user

    def _get_private(self):
        return bool(self.acl)

    def _set_private(self, bool_flag):
        if bool_flag:
            role_developer = ProjectRole.by_name('Developer')
            role_creator = ProjectRole.by_user(self.reported_by, upsert=True) if self.reported_by else None
            def _allow_all(role, perms):
                return [ACE.allow(role._id, perm) for perm in perms]
            # maintain existing access for developers and the ticket creator,
            # but revoke all access for everyone else
            acl = _allow_all(role_developer, security.all_allowed(self, role_developer))
            if role_creator and role_creator != ProjectRole.anonymous():
                acl += _allow_all(role_creator, security.all_allowed(self, role_creator))
            acl += [DENY_ALL]
            self.acl = acl
        else:
            self.acl = []
    private = property(_get_private, _set_private)

    def _set_discussion_disabled(self, is_disabled):
        """ Sets a ticket's discussion thread ACL to control a users ability to post.

        :param is_disabled: If True, an explicit deny will be created on the discussion thread ACL.
        """
        if is_disabled:
            self.discussion_thread.acl = [ACE.deny(EVERYONE, 'post'),
                                          ACE.deny(EVERYONE, 'unmoderated_post')]
        else:
            self.discussion_thread.acl = []

    def _get_discussion_disabled(self):
        """ Checks the discussion thread ACL to determine if users are allowed to post."""
        thread = Thread.query.get(ref_id=self.index_id())
        if thread:
            return bool(thread.acl)
        return False
    discussion_disabled = property(_get_discussion_disabled, _set_discussion_disabled)

    def commit(self, **kwargs):
        VersionedArtifact.commit(self)
        monitoring_email = self.app.config.options.get('TicketMonitoringEmail')
        if self.version > 1:
            hist = TicketHistory.query.get(
                artifact_id=self._id, version=self.version - 1)
            old = hist.data
            changes = ['Ticket %s has been modified: %s' % (
                self.ticket_num, self.summary),
                'Edited By: %s (%s)' % (c.user.get_pref('display_name'), c.user.username)]
            fields = [
                ('Summary', old.summary, self.summary),
                ('Status', old.status, self.status)]
            if old.status != self.status and self.status in c.app.globals.set_of_closed_status_names:
                h.log_action(log, 'closed').info('')
                g.statsUpdater.ticketEvent(
                    "closed", self, self.project, self.assigned_to)
            for key in self.custom_fields:
                fields.append(
                    (key, old.custom_fields.get(key, ''), self.custom_fields[key]))
            for title, o, n in fields:
                if o != n:
                    changes.append('%s updated: %r => %r' % (
                        title, o, n))
            o = hist.assigned_to
            n = self.assigned_to
            if o != n:
                changes.append('Owner updated: %r => %r' % (
                    o and o.username, n and n.username))
                self.subscribe(user=n)
                g.statsUpdater.ticketEvent("assigned", self, self.project, n)
                if o:
                    g.statsUpdater.ticketEvent(
                        "revoked", self, self.project, o)
            if old.description != self.description:
                changes.append('Description updated:')
                changes.append('\n'.join(
                    difflib.unified_diff(
                        a=old.description.split('\n'),
                        b=self.description.split('\n'),
                        fromfile='description-old',
                        tofile='description-new')))
            description = '\n'.join(changes)
        else:
            self.subscribe()
            if self.assigned_to_id:
                user = User.query.get(_id=self.assigned_to_id)
                g.statsUpdater.ticketEvent(
                    "assigned", self, self.project, user)
                self.subscribe(user=user)
            description = ''
            subject = self.email_subject
            Thread.new(discussion_id=self.app_config.discussion_id,
                       ref_id=self.index_id())
            # First ticket notification. Use persistend Message-ID (self.message_id()).
            # Thus we can group notification emails in one thread later.
            n = Notification.post(
                message_id=self.message_id(),
                artifact=self,
                topic='metadata',
                text=description,
                subject=subject)
            if monitoring_email and n and (not self.private or
                                           self.app.config.options.get('TicketMonitoringType') in (
                                               'NewTicketsOnly', 'AllTicketChanges')):
                n.send_simple(monitoring_email)
        Feed.post(
            self,
            title=self.summary,
            description=description if description else self.description,
            author=self.reported_by,
            pubdate=self.created_date)

    def url(self):
        return self.app_config.url() + str(self.ticket_num) + '/'

    def shorthand_id(self):
        return '#' + str(self.ticket_num)

    def assigned_to_name(self):
        who = self.assigned_to
        if who in (None, User.anonymous()):
            return 'nobody'
        return who.get_pref('display_name')

    def update(self, ticket_form):
        # update is not allowed to change the ticket_num
        ticket_form.pop('ticket_num', None)
        self.labels = ticket_form.pop('labels', [])
        custom_users = set()
        other_custom_fields = set()
        for cf in self.globals.custom_fields or []:
            (custom_users if cf['type'] == 'user' else
             other_custom_fields).add(cf['name'])
            if cf['type'] == 'boolean' and 'custom_fields.' + cf['name'] not in ticket_form:
                self.custom_fields[cf['name']] = 'False'
        # this has to happen because the milestone custom field has special
        # layout treatment
        if '_milestone' in ticket_form:
            other_custom_fields.add('_milestone')
            milestone = ticket_form.pop('_milestone', None)
            if 'custom_fields' not in ticket_form:
                ticket_form['custom_fields'] = dict()
            ticket_form['custom_fields']['_milestone'] = milestone
        attachment = None
        if 'attachment' in ticket_form:
            attachment = ticket_form.pop('attachment')
        for k, v in ticket_form.iteritems():
            if k == 'assigned_to':
                if v:
                    user = c.project.user_in_project(v)
                    if user:
                        self.assigned_to_id = user._id
            else:
                setattr(self, k, v)
        if 'custom_fields' in ticket_form:
            for k, v in ticket_form['custom_fields'].iteritems():
                if k in custom_users:
                    # restrict custom user field values to project members
                    user = self.app_config.project.user_in_project(v)
                    self.custom_fields[k] = user.username \
                        if user and user != User.anonymous() else ''
                elif k in other_custom_fields:
                    # strings are good enough for any other custom fields
                    self.custom_fields[k] = v
        if attachment is not None:
            self.add_multiple_attachments(attachment)
            # flush the session to make attachments available in the
            # notification email
            ThreadLocalORMSession.flush_all()
        self.commit()

    def _move_attach(self, attachments, attach_metadata, app_config):
        for attach in attachments:
            attach.app_config_id = app_config._id
            if attach.attachment_type == 'DiscussionAttachment':
                attach.discussion_id = app_config.discussion_id
            attach_thumb = BaseAttachment.query.get(
                filename=attach.filename, **attach_metadata)
            if attach_thumb:
                if attach_thumb.attachment_type == 'DiscussionAttachment':
                    attach_thumb.discussion_id = app_config.discussion_id
                attach_thumb.app_config_id = app_config._id

    def move(self, app_config, notify=True):
        '''Move ticket from current tickets app to tickets app with given app_config'''
        app = app_config.project.app_instance(app_config)
        prior_url = self.url()
        prior_app = self.app
        prior_ticket_num = self.ticket_num
        attachments = self.attachments
        attach_metadata = BaseAttachment.metadata_for(self)
        prior_cfs = [
            (cf['name'], cf['type'], cf['label'])
            for cf in prior_app.globals.custom_fields or []]
        new_cfs = [
            (cf['name'], cf['type'], cf['label'])
            for cf in app.globals.custom_fields or []]
        skipped_fields = []
        user_fields = []
        for cf in prior_cfs:
            if cf not in new_cfs:  # can't convert
                skipped_fields.append(cf)
            elif cf[1] == 'user':  # can convert and field type == user
                user_fields.append(cf)
        messages = []
        for cf in skipped_fields:
            name = cf[0]
            messages.append('- **%s**: %s' %
                            (name, self.custom_fields.get(name, '')))
        for cf in user_fields:
            name = cf[0]
            username = self.custom_fields.get(name, None)
            user = app_config.project.user_in_project(username)
            if not user or user == User.anonymous():
                messages.append('- **%s**: %s (user not in project)' %
                                (name, username))
                self.custom_fields[name] = ''
        # special case: not custom user field (assigned_to_id)
        user = self.assigned_to
        if user and not app_config.project.user_in_project(user.username):
            messages.append('- **assigned_to**: %s (user not in project)' %
                            user.username)
            self.assigned_to_id = None

        custom_fields = {}
        for cf in new_cfs:
            fn, ft, fl = cf
            old_val = self.custom_fields.get(fn, None)
            if old_val is None:
                custom_fields[fn] = None if ft == 'user' else ''
            custom_fields[fn] = old_val
        self.custom_fields = custom_fields

        # move ticket. ensure unique ticket_num
        while True:
            with h.push_context(app_config.project_id, app_config_id=app_config._id):
                ticket_num = app.globals.next_ticket_num()
            self.ticket_num = ticket_num
            self.app_config_id = app_config._id
            new_url = app_config.url() + str(self.ticket_num) + '/'
            try:
                session(self).flush(self)
                h.log_action(log, 'moved').info('Ticket %s moved to %s' %
                                                (prior_url, new_url))
                break
            except OperationFailure, err:
                if 'duplicate' in err.args[0]:
                    log.warning(
                        'Try to create duplicate ticket %s when moving from %s' %
                        (new_url, prior_url))
                    session(self).expunge(self)
                    continue

        attach_metadata['type'] = 'thumbnail'
        self._move_attach(attachments, attach_metadata, app_config)

        # move ticket's discussion thread, thus all new commnets will go to a
        # new ticket's feed
        self.discussion_thread.app_config_id = app_config._id
        self.discussion_thread.discussion_id = app_config.discussion_id
        for post in self.discussion_thread.posts:
            attach_metadata = BaseAttachment.metadata_for(post)
            attach_metadata['type'] = 'thumbnail'
            self._move_attach(post.attachments, attach_metadata, app_config)
            post.app_config_id = app_config._id
            post.app_id = app_config._id
            post.discussion_id = app_config.discussion_id

        session(self.discussion_thread).flush(self.discussion_thread)
        # need this to reset app_config RelationProperty on ticket to a new one
        session(self.discussion_thread).expunge(self.discussion_thread)
        session(self).expunge(self)
        ticket = Ticket.query.find(dict(
            app_config_id=app_config._id, ticket_num=self.ticket_num)).first()

        # creating MovedTicket to be able to redirect from this url
        moved_ticket = MovedTicket(
            app_config_id=prior_app.config._id, ticket_num=prior_ticket_num,
            moved_to_url=ticket.url(),
        )

        message = 'Ticket moved from %s' % prior_url
        if messages:
            message += '\n\nCan\'t be converted:\n\n'
        message += '\n'.join(messages)
        with h.push_context(ticket.project_id, app_config_id=app_config._id):
            ticket.discussion_thread.add_post(text=message, notify=notify)
        return ticket

    def attachments_for_export(self):
        return [dict(bytes=attach.length,
                     url=h.absurl(attach.url()),
                     path=os.path.join(
                         self.app_config.options.mount_point,
                         str(self._id),
                         os.path.basename(attach.filename))) for attach in self.attachments]

    def attachments_for_json(self):
        return [dict(bytes=attach.length,
                     url=h.absurl(attach.url())) for attach in self.attachments]

    def __json__(self, posts_limit=None, is_export=False):
        parents_json = {}
        for parent in reversed(type(self).mro()):
            if parent != type(self) and hasattr(parent, '__json__'):
                kwargs = {}
                if parent == VersionedArtifact:
                    kwargs['posts_limit'] = posts_limit
                try:
                    parents_json.update(parent.__json__(self, is_export=is_export, **kwargs))
                except:
                    parents_json.update(parent.__json__(self, **kwargs))

        return dict(parents_json,
                    created_date=self.created_date,
                    ticket_num=self.ticket_num,
                    summary=self.summary,
                    description=self.description,
                    reported_by=self.reported_by_username,
                    assigned_to=self.assigned_to_id and self.assigned_to_username or None,
                    reported_by_id=self.reported_by_id and str(
                        self.reported_by_id) or None,
                    assigned_to_id=self.assigned_to_id and str(
                        self.assigned_to_id) or None,
                    status=self.status,
                    private=self.private,
                    discussion_disabled=self.discussion_disabled,
                    attachments=self.attachments_for_export() if is_export else self.attachments_for_json(),
                    custom_fields=dict(self.custom_fields))

    @classmethod
    def paged_query(cls, app_config, user, query, limit=None, page=0, sort=None, deleted=False, **kw):
        """
        Query tickets, filtering for 'read' permission, sorting and paginating the result.

        See also paged_search which does a solr search
        """
        limit, page, start = g.handle_paging(limit, page, default=25)
        q = cls.query.find(
            dict(query, app_config_id=app_config._id, deleted=deleted))
        q = q.sort('ticket_num', pymongo.DESCENDING)
        if sort:
            field, direction = sort.split()
            if field.startswith('_'):
                field = 'custom_fields.' + field
            direction = dict(
                asc=pymongo.ASCENDING,
                desc=pymongo.DESCENDING)[direction]
            q = q.sort(field, direction)
        q = q.skip(start)
        q = q.limit(limit)
        tickets = []
        count = q.count()
        for t in q:
            if security.has_access(t, 'read', user, app_config.project.root_project):
                tickets.append(t)
            else:
                count = count - 1

        return dict(
            tickets=tickets,
            count=count, q=json.dumps(query), limit=limit, page=page, sort=sort,
            **kw)

    @classmethod
    def paged_search(cls, app_config, user, q, limit=None, page=0, sort=None, show_deleted=False,
                     filter=None, **kw):
        """Query tickets from Solr, filtering for 'read' permission, sorting and paginating the result.

        See also paged_query which does a mongo search.

        We do the sorting and skipping right in SOLR, before we ever ask
        Mongo for the actual tickets.  Other keywords for
        search_artifact (e.g., history) or for SOLR are accepted through
        kw.  The output is intended to be used directly in templates,
        e.g., exposed controller methods can just:

            return paged_query(q, ...)

        If you want all the results at once instead of paged you have
        these options:
          - don't call this routine, search directly in mongo
          - call this routine with a very high limit and TEST that
            count<=limit in the result
        limit=-1 is NOT recognized as 'all'.  500 is a reasonable limit.
        """

        limit, page, start = g.handle_paging(limit, page, default=25)
        count = 0
        tickets = []
        if filter is None: filter = {}
        refined_sort = sort if sort else 'ticket_num_i desc'
        if 'ticket_num_i' not in refined_sort:
            refined_sort += ',ticket_num_i asc'
        try:
            if q:
                # also query for choices for filter options right away
                params = kw.copy()
                params.update(tsearch.FACET_PARAMS)
                if not show_deleted:
                    params['fq'] = ['deleted_b:False']

                matches = search_artifact(
                    cls, q, short_timeout=True,
                    rows=limit, sort=refined_sort, start=start, fl='id',
                    filter=filter, **params)
            else:
                matches = None
            solr_error = None
        except SearchError as e:
            solr_error = e
            matches = None
        if matches:
            count = matches.hits
            # ticket_matches is in sorted order
            ticket_matches = [ObjectId(match['id'].split('#')[1]) for match in matches.docs]
            query = cls.query.find(
                dict(_id={'$in': ticket_matches}))
            # so stick all the results in a dictionary...
            ticket_by_id = {}
            for t in query:
                ticket_by_id[t._id] = t
            # and pull them out in the order given by ticket_numbers
            tickets = []
            for t_id in ticket_matches:
                if t_id in ticket_by_id:
                    show_deleted = show_deleted and security.has_access(
                        ticket_by_id[t_id], 'delete', user, app_config.project.root_project)
                    if (security.has_access(ticket_by_id[t_id], 'read', user,
                                            app_config.project.root_project if app_config else None) and
                            (show_deleted or ticket_by_id[t_id].deleted == False)):
                        tickets.append(ticket_by_id[t_id])
                    else:
                        count = count - 1
        return dict(tickets=tickets,
                    count=count, q=q, limit=limit, page=page, sort=sort,
                    filter=filter,
                    filter_choices=tsearch.get_facets(matches),
                    solr_error=solr_error, **kw)

    @classmethod
    def paged_query_or_search(cls, app_config, user, query, search_query, filter,
                              limit=None, page=0, sort=None, **kw):
        """Switch between paged_query and paged_search based on filter.

        query - query in mongo syntax
        search_query - query in solr syntax
        """
        solr_sort = None
        if sort:
            from forgetracker.tracker_main import _mongo_col_to_solr_col
            sort_split = sort.split(' ')
            solr_col = _mongo_col_to_solr_col(sort_split[0])
            solr_sort = '%s %s' % (solr_col, sort_split[1])
        if not filter:
            result = cls.paged_query(app_config, user, query, sort=sort, limit=limit, page=page, **kw)
            t = cls.query.find().first()
            if t:
                search_query = cls.translate_query(search_query, t.index())
            result['filter_choices'] = tsearch.query_filter_choices(
                search_query, fq=[] if kw.get('show_deleted', False) else ['deleted_b:False'])
        else:
            result = cls.paged_search(app_config, user, search_query, filter=filter,
                                      sort=solr_sort, limit=limit, page=page, **kw)

        result['sort'] = sort
        result['url_sort'] = solr_sort if solr_sort else ''
        return result

    def get_mail_footer(self, notification, toaddr):
        if toaddr and toaddr == self.monitoring_email:
            return MailFooter.monitored(
                toaddr,
                h.absurl(self.app.url),
                h.absurl('{0}admin/{1}/options'.format(
                    self.project.url(),
                    self.app.config.options.mount_point)))
        return MailFooter.standard(
            notification,
            self.app.config.options.get('AllowEmailPosting', True),
            discussion_disabled=self.discussion_disabled)

    def soft_delete(self):
        require_access(self, 'delete')
        Shortlink.query.remove(dict(ref_id=self.index_id()))
        self.deleted = True
        suffix = " {dt.hour}:{dt.minute}:{dt.second} {dt.day}-{dt.month}-{dt.year}".format(
            dt=datetime.utcnow())
        self.summary += suffix
        c.app.globals.invalidate_bin_counts()


class TicketAttachment(BaseAttachment):
    thumbnail_size = (100, 100)
    ArtifactType = Ticket

    class __mongometa__:
        polymorphic_identity = 'TicketAttachment'
    attachment_type = FieldProperty(str, if_missing='TicketAttachment')


class MovedTicket(MovedArtifact):

    class __mongometa__:
        session = artifact_orm_session
        name = 'moved_ticket'
        indexes = [
            ('app_config_id', 'ticket_num'),
        ]

    ticket_num = FieldProperty(int, required=True, allow_none=False)

    def url(self):
        return self.moved_to_url

Mapper.compile_all()
