# -*- coding: utf-8 -*-
# TicketListOverrayPlugin
import re
import logging

from genshi.filters import Transformer

from trac.core import *
from trac.config import Option, BoolOption,  Configuration
from trac.web.chrome import ITemplateProvider, add_stylesheet, add_script
from trac.web.api import IRequestFilter, IRequestHandler
from trac.ticket.report import ReportModule
from trac.util import escape, Markup
from trac.wiki import Formatter
from trac.perm import IPermissionRequestor

from pkg_resources import resource_filename


class TicketListOverrayPlugin(Component):
    implements( IRequestHandler ,ITemplateProvider ,IRequestFilter )

    reports = Option( 'ticketlistoverray', 'reports', '7,1',
            u"""表示するレポートのIDをカンマ区切りで指定します。""")
    max_count = Option( 'ticketlistoverray', 'max_count', '5',
            u"""ひとつのレポートあたりに表示するチケットの件数を指定します。""")
    link_target_new = BoolOption('ticketlistoverray',  'link_target_new', 'true',
            u"""リンクをクリックした際に新しいウィンドウで開くかを設定します。""")
    default_visibility = BoolOption('ticketlistoverray',  'default_visibility', 'true',
            u"""最初から一覧を開いた状態で表示するか設定します。""")
    top = Option( 'ticketlistoverray', 'top', '200',
            u"""レポートのオーバーレイを表示する絶対座標(Top)です。""")
    left = Option( 'ticketlistoverray', 'left', '680',
            u"""レポートのオーバーレイを表示する絶対座標(Left)です。""")
    width = Option( 'ticketlistoverray', 'width', '380',
            u"""レポートのオーバーレイのサイズ(width)です。""")
    height = Option( 'ticketlistoverray', 'height', '480',
            u"""レポートのオーバーレイのサイズ(height)です。""")

    id_ptn = re.compile(r"""id\s+AS\s+([^, ]+)\s?,""" )
    sum_ptn = re.compile(r"""summary\s+AS\s+([^,]+)\s?,""" )


    # ITemplateProvider methods

    def get_templates_dirs(self):
        yield resource_filename(__name__, 'templates')

    def get_htdocs_dirs(self):
        yield 'ticketlistoverray', resource_filename(__name__, 'htdocs')


    # IRequestHandler methods

    def match_request(self, req):
        return re.match(r'^/TicketListOverray(?:(.*))', req.path_info) is not None

    def process_request(self, req):

        if re.match(r'^/TicketListOverray/ticketlistoverray.js',req.path_info) :
            return self.process_script( req )

        report = req.args.get('report') or ""

        if report:
            result = self.process_report( req, report )
        else:
            logging.warning('TicketListOverray: report is brank.')

        req.send_response(200)
        req.send_header('Content-Type', 'text/html')
        req.end_headers()
        req.write(result)

    # IRequestFilter methods

    def post_process_request(self, req, template, data, content_type):
        if not re.match(r'^/TicketListOverray/ticketlistoverray.js',req.path_info) :
            add_script(req, '/TicketListOverray/ticketlistoverray.js')
        if not re.match(r'^ticketlistoverray/ticketlistoverray.css',req.path_info) :
            add_stylesheet(req, 'ticketlistoverray/ticketlistoverray.css')
        if not re.match(r'^ticketlistoverray/jquery-ui-1.6.custom.min.js',req.path_info) :
            add_script(req, 'ticketlistoverray/jquery-ui-1.6.custom.min.js')

        return template, data, content_type

    def pre_process_request(self, req, handler):
        return handler

    # ticketlistoverray.jsに対してのRequestを処理して
    # Overrayをloadするjavascriptを生成して返す
    def process_script( self , req ):
        load_script = ""
        for report_id in self.reports.split(","):
            load_script += """
    $('#TicketListOverray_Box').append("<div id='TicketListOverray_Report_%s' />")
    $("#TicketListOverray_Report_%s").addClass("TicketListOverray_Report");
    $("#TicketListOverray_Report_%s").load( "%s/TicketListOverray?report=%s");
""" % ( report_id, report_id, report_id, req.base_url, report_id )

        if self.default_visibility :
            hidden_code = ""
        else:
            hidden_code = """$('#TicketListOverray_Box').hide();"""

        result = """
$(function(){
    $("div#footer").after("<div id='TicketListOverray_Container' />")
    $('div#TicketListOverray_Container')
        .css( "max-width", %s )
        .css( "max-height", %s )
        .css( "top" ,  %s )
        .css( "left",  %s );
    $('#TicketListOverray_Container').append("<span id='TicketListOverray_Button'></span>")
    $('#TicketListOverray_Container').append("<span id='TicketListOverray_Title'> Report List </span>")
    $('#TicketListOverray_Container').append("<div id='TicketListOverray_Box' />")

    $('span#TicketListOverray_Button').click( function(){
        $('div#TicketListOverray_Box').toggle('normal');
    });

    $('#TicketListOverray_Container').draggable();

    %s

    %s
 });
""" % ( self.width,
        self.height,
        self.top,
        self.left,
        hidden_code,
        load_script )

        req.send_response(200)
        req.send_header('Content-Type', 'text/javascript')
        req.end_headers()
        req.write(result)

    # 指定されたReportの検索結果を出力する
    def process_report(self, req, report_id ):

        report = self.get_report( report_id )

        if len( report ) == 1:
            title, sql, desc = report[0]
            cols, results, num_items = self.execute_report( req, report_id, sql )
            return self.render_report( req, report_id, title, sql, cols, results, num_items )

        else:
            raise ResourceNotFound(
                'Report [%s] does not exist.Invalid Report Number' % report_id  )

    # Reportの検索結果を整形する
    def render_report( self, req, report_id, title, sql, cols, results, num_items ):
        if self.id_ptn.search( sql ):
            id_col = self.id_ptn.search( sql ).group(1)
        else:
            logging.warning("TicketListOverrayPlugin: report[%s] does not contains id.output aborted." % report_id )
            return ""

        if self.sum_ptn.search( sql ):
            sum_col = self.sum_ptn.search( sql ).group(1)
        else:
            logging.warning("TicketListOverrayPlugin: report[%s] does not contains summary.output aborted." % report_id )
            return ""

        if self.link_target_new:
            link_target = "target='_blank'"
        else:
            link_target = ""

        id_idx = cols.index( id_col )
        sum_idx = cols.index( sum_col )

        s = """<hr/><span><a href="%s" %s>%s</a>(%s)<span>""" % ( req.href('report', report_id),
                link_target, title, num_items )

        s += """<table>"""
        for ticket in results:
            ticket_id = ticket[id_idx]
            summary = ticket[sum_idx]
            url = req.href('ticket', ticket_id )
            s +="""  <tr><td><a href="%s" %s>#%s</a></td><td><a href="%s" %s>%s</a></td></tr>""" % (
                    url, link_target, ticket_id, url, link_target,  summary )

        s += """</table>"""

        return s

    # Reportの情報を返す
    def get_report(self, report):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute("SELECT title,query,description from report "
                       "WHERE id=%s", (report,))

        report = [(title, sql, desc) for title, sql, desc in cursor]
        return report

    # Reportの検索結果を返す
    def execute_report(self, req, report_id, sql ):

        db = self.env.get_db_cnx()
        rm = ReportModule(self.env)

        args = rm.get_var_args(req)

        limit = self.max_count
        offset = 0

        cols, results, num_items = rm.execute_paginated_report(
                req, db, report_id, sql, args, limit, offset)
        results = [list(row) for row in results]
        numrows = len(results)

        return cols,  results , num_items




