#!-*- coding:utf-8 -*-"

import calendar
import datetime
import pkg_resources
import re
import time

from datetime import datetime, date, timedelta
from decimal import Decimal

from genshi.builder import tag
from genshi.filters import Transformer
from genshi.filters.transform import StreamBuffer
from genshi.template.markup import MarkupTemplate

from trac.core import *
from trac.mimeview.api import Mimeview, IContentConverter, Context
from trac.perm import IPermissionGroupProvider, IPermissionRequestor, PermissionSystem
from trac.ticket import Ticket
from trac.ticket.api import ITicketManipulator
from trac.ticket.api import ITicketChangeListener
from trac.ticket.query import Query
from trac.util.datefmt import to_timestamp, utc, format_date, parse_date
from trac.util.translation import _
from trac.web.api import IRequestHandler
from trac.web.api import ITemplateStreamFilter
from trac.web.chrome import INavigationContributor
from trac.web.chrome import ITemplateProvider
from trac.web.chrome import add_ctxtnav
from trac.web.chrome import add_link 
from trac.web.chrome import add_script
from trac.web.chrome import add_stylesheet
from trac.web.chrome import Chrome
from trac.web.chrome import INavigationContributor

# local imports
from dateutils import *
from utils import *
from dbhelper import *

class TicketWebUIExt(Component):

    group_providers = ExtensionPoint(IPermissionGroupProvider)
    
    ###### class data
    #date_format = '%B %d, %Y'     # XXX should go to api ?
    date_format = '%Y/%m/%d'
    hours_regex = '(([0-9]+(\.[0-9]+)?)|([0-9]+:[0-5][0-9])) *hours' # for ticket comments: 1.5 hours or 1:30 hours
    singular_hour_regex = r'((^)|(\s))1 *hour((\W)|($))' # for singular hours: 1 hour

    ###### methods and attributes for trac Interfaces
    implements(IRequestHandler,
               ITemplateProvider,
               ITemplateStreamFilter
               )
    
    ### methods for IRequestHandler
    def match_request(self, req):
        path = req.path_info.rstrip('/')
        if not path.startswith('/timingandestimationext'):
            return False
        return True

    def process_request(self, req):
        assert_modify_permission(self.env, req)
        
        ticket_id = req.args.get('ticket_id')
        date_str = req.args.get('timingandestimationext_date')
        hours = req.args.get('timingandestimationext_hour')
        
        try:
            date = str_to_datetime(req, date_str)
        except:
            from trac.web.chrome import add_warning
            add_warning(req, u"正しい日付を入力してください。 ")
            req.redirect(req.href.ticket(ticket_id))
        try:
            float(hours)
            int(ticket_id)
        except:
            from trac.web.chrome import add_warning
            add_warning(req, u"正しい時間を入力してください。")
            req.redirect(req.href.ticket(ticket_id))
        
        self._add_hours(req, ticket_id, date, hours)
        
        from trac.web.chrome import add_notice
        add_notice(req, u"チケット #%s の作業時間として、%s に %s 時間追加しました。" % (ticket_id, date_str, hours))
        
        req.redirect(req.href.ticket(ticket_id))
        
    def _add_hours(self, req, ticket_id, date, hours):
        db = self.env.get_db_cnx()
        add_ticket_change(db, ticket_id, req.authname, date, hours, self.env.log)

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

    def get_templates_dirs(self):
        from pkg_resources import resource_filename
        return [resource_filename(__name__, 'templates')]

    # ITemplateStreamFilter methods
    def filter_stream(self, req, method, filename, stream, data):
        match = re.match(r'/ticket/([0-9]+)$', req.path_info)
        if not match:
            return stream
        
        ticket_id = match.group(1)
        
        # check permission
        ticket = Ticket(self.env, ticket_id)
        if 'TICKET_CHGPROP' not in req.perm(ticket.resource):
            return stream
            
        add_script(req,'timingandestimationext/js/jquery-ui-1.8.2.custom.min.js')
        add_stylesheet(req, "timingandestimationext/css/ui-lightness/jquery-ui-1.8.2.custom.css")
        add_stylesheet(req, 'timingandestimationext/css/timingandestimationext.css')
        add_stylesheet(req, 'timingandestimationext/treetable/stylesheets/jquery.treeTable.css')
        
        my_works = self._get_my_works(ticket_id, req.authname)
        my_works = [(format_utcepoch(x[0]), x[1]) for x in my_works if x[1] and float(x[1]) > 0]
        my_works_sum = sum([float(x[1]) for x in my_works])
        
        data = {'req': req, 'ticket_id': ticket_id, 'today': today(),
                'my_works': my_works, 'my_works_sum': my_works_sum}
        html = template(self.env, 'timigandestimationext_panel.html', data)
        
        timingandestimationext_PATH = '//div[@id="ctxtnav"]'
        stream |= Transformer(timingandestimationext_PATH).after(html)
            
        return stream

    def _get_my_works(self, ticket_id, authname):
        db = self.env.get_db_cnx()
        return get_my_works(db, ticket_id, authname, self.env.log)
        
