# -*- coding: utf-8 -*-

import pkg_resources
import threading
                
from trac.core import *
from trac.ticket import ITicketChangeListener, Ticket
from trac.web.api import ITemplateStreamFilter, IRequestFilter
from trac.web.chrome import add_script, add_stylesheet, ITemplateProvider

from genshi.builder import tag
from genshi.filters import Transformer

revision = "$Rev: 8087 $"
url = "$URL: http://svn.edgewall.org/repos/trac/branches/0.11-stable/sample-plugins/ticket_clone.py $"

class SimpleTicketCloneButton(Component):
    """Add a 'Clone' button to the ticket box. 
    
    This button is located next to the 'Reply' to description button,
    and pressing it will send a request for creating a new ticket
    which will be based on the cloned one.
    """
       
    implements(ITemplateProvider, ITemplateStreamFilter, IRequestFilter)

    # ITemplateProvider methods
    def get_htdocs_dirs(self):
        return [('ticketclone', pkg_resources.resource_filename(__name__, 'htdocs'))]

    def get_templates_dirs(self):
        return []

    # ITemplateStreamFilter methods
    def filter_stream(self, req, method, filename, stream, data):
        ticketclone_id = req.args.get('ticketclone_id')
        if ticketclone_id:
            add_script(req, 'ticketclone/js/ticketclone.js')
            filter = Transformer('//fieldset[@id="properties"]')
            return stream | filter.after(self._checkbox_notify(req, ticketclone_id))
        if filename == 'ticket.html':
            ticket = data.get('ticket')
            if ticket and ticket.exists and \
                    'TICKET_ADMIN' in req.perm(ticket.resource):
                filter = Transformer('//h3[@id="comment:description"]')
                return stream | filter.after(self._clone_form(req, ticket, data))
        return stream
    
    def _checkbox_notify(self, req, ticketclone_id):
        notify = req.args.get('ticketclone_notify')
        return tag.p(
            tag.label(
                tag.input(type="hidden", name="ticketclone_id", value=ticketclone_id),
                tag.input(id="ticketclone_notify", type="checkbox", name="ticketclone_notify",
                          checked=notify == 'on' and 'checked' or None),'\n',
                u"複製元のチケット(#%s)にコメントを記録します。" % ticketclone_id
            )
        ) + tag.p(
            'コメントの追加:', '\n',
            tag.label(
                tag.input(name="ticketclone_comment", size="70",
                          value=req.args.get("ticketclone_comment"))
            ), id="ticketclone_comment", style="display:none;"
        )

    def _clone_form(self, req, ticket, data):
        fields = {}
        for f in data.get('fields', []):
            name = f['name']
            if name == 'summary':
                fields['summary'] = ticket['summary'] + " (cloned)"
            elif name == 'description':
                fields['description'] = "Cloned from #%s: \n----\n%s" % \
                    (ticket.id, ticket['description'])
            else:
                fields[name] = ticket[name]
        return tag.form(
            tag.div(
                tag.input(type="submit", name="clone", value="Clone",
                    title="Create a copy of this ticket"),
                tag.input(type="hidden", name="ticketclone_id", value=ticket.id),
                [tag.input(type="hidden", name='field_'+n, value=v) for n, v in
                    fields.items()],
                tag.input(type="hidden", name='preview', value=''),
                class_="inlinebuttons"),
            method="post", action=req.href.newticket())

    # IRequestFilter methods
    def pre_process_request(self, req, handler):
        if req.path_info.startswith('/newticket'):
            notify = req.args.get('ticketclone_notify')
            if notify == 'on':
                ticketclone_id = req.args.get('ticketclone_id')
                ticketclone_comment = req.args.get('ticketclone_comment')
                threading.currentThread()._ticketclone_id = ticketclone_id
                if ticketclone_comment and len(ticketclone_comment.strip()) > 0:
                    threading.currentThread()._ticketclone_comment = ticketclone_comment
                
        return handler
        
    def post_process_request(self, req, template, data, content_type):
        return template, data, content_type
    
class TicketCloneObserver(Component):
    implements(ITicketChangeListener)

    def ticket_created(self, ticket):
        if threading.currentThread().__dict__.has_key('_ticketclone_id'):
            ticketclone_id = threading.currentThread().__dict__.pop('_ticketclone_id')
              
            if ticketclone_id:
                base_ticket = Ticket(self.env, ticketclone_id)
                comment = u'チケットを複製しました。-- #%s' % ticket.id
                
                if threading.currentThread().__dict__.has_key('_ticketclone_comment'):
                    ticketclone_comment = threading.currentThread().__dict__.pop('_ticketclone_comment')
                    if ticketclone_comment:
                        comment = comment + '[[BR]][[BR]]' + ticketclone_comment
                    
                base_ticket.save_changes(ticket['reporter'], comment)
                
        """Called when a ticket is created."""

    def ticket_changed(self, ticket, comment, author, old_values):
        """Called when a ticket is modified."""

    def ticket_deleted(self, ticket):
        """Called when a ticket is deleted."""

