# encoding: utf-8

import re
try:
    import json
except ImportError:
    import simplejson as json

from genshi.filters.transform import Transformer
from genshi.template import MarkupTemplate

from api import InformData

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

_TRUE_VALUES = ('true', 'enabled', '1', 1, True, 'on')

class InformRegister(Component):
    implements(ITemplateProvider, IRequestFilter, ITemplateStreamFilter, ITicketChangeListener)
    
    _question = ''
    _yes = ''
    _no = ''

    # ITemplateProvider method
    def get_htdocs_dirs(self):
        from pkg_resources import resource_filename
        return [('inform', resource_filename(__name__, 'htdocs'))]

    # ITemplateProvider method
    def get_templates_dirs(self):
        from pkg_resources import resource_filename
        return [resource_filename(__name__, 'templates')]
    
    # IRequestFilter method
    def pre_process_request(self, req, handler):
        if 'preview' in req.args:
            return handler

        if req.path_info != '/newticket' and req.path_info.find('/ticket') != 0:
            self._question = ''
            self._yes = ''
            self._no = ''
            return handler

        inform = req.args.get('inform')
        if inform is None:
            self._question = ''
            self._yes = ''
            self._no = ''
            inform = "false"
        if inform.lower() in _TRUE_VALUES:
            self._question = req.args.get('inform_question')
            self._yes = req.args.get('inform_yes')
            self._no = req.args.get('inform_no')
        else:
            self._question = ''
            self._yes = ''
            self._no = ''
        
        if req.path_info.find('/ticket') == 0:
            if req.args.get("action") is not None and req.args.get("submit") is not None:
                self.update(req.args.get("id"))

        return handler
    
    # IRequestFilter method
    def post_process_request(self, req, template, content_type):
        return (template, content_type)
    
    # IRequestFilter method
    def post_process_request(self, req, template, data, content_type):
        if template == 'ticket.html':
            add_script(req, 'inform/js/inform_vote.js')
            
        return (template, data, content_type)
    
    # ITemplateStreamFilter method
    def filter_stream(self, req, method, filename, stream, data):
        if filename != 'ticket.html':
            return stream
        
        # if specify disable, not execute.
        enable = True
        if 'inform' in req.args:
            enable = req.args['inform']
            enable = enable.lower() in _TRUE_VALUES
            enable = bool(enable)
        if not enable:
            return stream
        
        readyDescription = False
        if req.path_info == '/newticket' and 'preview' not in req.args:
            readyDescription = True
        
        # DBより周知事項情報取得
        question = ''
        yes = ''
        no = ''
        checked = ''
        if readyDescription == False and req.args.get('id') is not None:
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            sql = "SELECT question,yes,no  FROM inform WHERE ticket=%s"
            cursor.execute(sql % (req.args.get('id')))
            row = cursor.fetchone()
            if row is not None:
                question = row[0]
                yes = row[1]
                no = row[2]
            if question != '':
                checked = 'checked="true"'
                
        div = u'\n<fieldset id="inform_input" name="inform_input">'\
            + u'<legend>周知事項</legend>\n'\
            + u'<label>\n'\
            + u'<input type="checkbox" name="inform" id="inform" value="true" %s/>\n' % (checked)\
            + u'このチケットで周知管理を行う\n'\
            + u'</label>\n'\
            + u'<table id="inform_input_data" name="inform_input_data">\n'\
            + u'<tr>\n'\
            + u'<th><label>問い合わせ内容:</label></th>\n'\
            + u'<td><input type="text" id="inform_question" name="inform_question" value="%s" size="70" /></td>\n' % (question)\
            + u'</tr>\n'\
            + u'<tr>\n'\
            + u'<th><label>回答内容１（yes）:</label></th>\n'\
            + u'<td><input type="text" id="inform_yes" name="inform_yes" value="%s" size="40" /></td>\n' % (yes)\
            + u'</tr>\n'\
            + u'<tr>\n'\
            + u'<th><label>回答内容２（no）:</label></th>\n'\
            + u'<td><input type="text" id="inform_no" name="inform_no" value="%s" size="40" /></td>\n' % (no)\
            + u'</tr>\n'\
            + u'</table>\n'\
            + u'</fieldset>\n'

        script = '\n<script type="text/javascript">\n'\
               + '$(function(){informInputCheckLoad()});\n'\
               + '</script>\n'
        
        return stream | Transformer('//div[@class="buttons"]').before(MarkupTemplate(div).generate()) \
                      | Transformer('//div[@id="footer"]').before(MarkupTemplate(script).generate())

    def ticket_created(self, ticket):
        self.update(ticket.id)

    def ticket_changed(self, ticket, comment, author, old_values):
        pass

    def ticket_deleted(self, ticket):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        sql = "DELETE FROM inform WHERE ticket=%d"
        cursor.execute(sql % (ticket.id))
        db.commit()

    # informテーブルに対する更新を行います
    def update(self, id):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        
        if id == '' or id is None:
            return
        if self._question == '' or self._question is None:
            sql = "DELETE FROM inform WHERE ticket=%s"
            cursor.execute(sql % (id))
            db.commit()
            return
        if self._yes == '' or self._yes is None:
            return
        if self._no == '' or self._no is None:
            return
        
        try:
            sql = "INSERT INTO inform(ticket,question,yes,no,yesuser,nouser) VALUES(%s,'%s','%s','%s','','')"
            cursor.execute(sql % (id, self._question, self._yes, self._no))
        except Exception, e:
            pass
        
        sql = "UPDATE inform SET question='%s',yes='%s',no='%s' WHERE ticket=%s"
        cursor.execute(sql % (self._question, self._yes, self._no, id))
        db.commit()
        
        self._question = ''
        self._yes = ''
        self._no = ''

class InformVote(Component):
    implements(IRequestFilter, ITemplateStreamFilter, IRequestHandler)
    
    # IRequestFilter method
    def pre_process_request(self, req, handler):
        return handler
    
    # IRequestFilter method
    def post_process_request(self, req, template, content_type):
        return (template, content_type)
    
    # IRequestFilter method
    def post_process_request(self, req, template, data, content_type):
        if template == 'ticket.html':
            add_stylesheet(req, 'inform/css/ui-lightness/ui.all.css')
            add_script(req, 'inform/js/ui.core.js')
            add_script(req, 'inform/js/ui.dialog.js')
            add_script(req, 'inform/js/ui.draggable.js')
            add_script(req, 'inform/js/ui.resizable.js')
            add_script(req, 'inform/js/inform_vote.js')
            
        return (template, data, content_type)
    
    # ITemplateStreamFilter method
    def filter_stream(self, req, method, filename, stream, data):
        if filename != 'ticket.html':
            return stream
        if req.path_info.find('/ticket') != 0:
            return stream
        
        # DBより周知事項情報取得
        question = ''
        yes = ''
        no = ''
        checked = ''
        if req.args.get('id') is not None:
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            sql = "SELECT question,yes,no FROM inform WHERE ticket=%s"
            cursor.execute(sql % (req.args.get('id')))
            row = cursor.fetchone()
            if row is not None:
                question = row[0]
                yes = row[1]
                no = row[2]
            if question != '':
                checked = 'checked="true"'
        if question == '':
            return stream
        if yes == '':
            return stream
        if no == '':
            return stream
        
        script = 'informDialog(\'%s\',\'%s\',\'%s\',\'%s\',inform_send);' % (question, u'周知事項確認', yes, no)
        
        # 関係者情報取得
        sql = "SELECT cc FROM ticket WHERE id=%s"
        cursor.execute(sql % (req.args.get('id')))
        row = cursor.fetchone()
        if row is None:
            return stream
        cc = row[0].replace(' ', '')
        cclist = cc.split(',')
        
        input = ''
        if req.authname in cclist:
            input = u'<input id="inform_button" name="inform_button" type="button" value="周知確認" onclick="%s" />\n' % (script)
        
        div = u'\n<div id="inform_vote" name="inform_vote">'\
            + u'<h3 id="comment:description">周知管理</h3>\n'\
            + u'<script type="text/javascript">\n'\
            + u'  inform_send = function(cancel){\n'\
            + u'    var data = {"result":cancel,"id":"%s"};\n' % (req.args.get('id'))\
            + u'    $.ajax({\n'\
            + u'      type: "GET",\n'\
            + u'      cache : false,\n'\
            + u'      dataType: "json",\n'\
            + u'      url: "%s/inform_update",\n' % (req.base_url)\
            + u'      data: data,'\
            + u'      success: function(msg){\n'\
            + u'        inform_view("%s/inform_view","%s");\n' % (req.base_url, (req.args.get('id'))) \
            + u'      }\n'\
            + u'    });\n'\
            + u'  };\n'\
            + u'</script>\n'\
            + u'%s' % (input)\
            + u'</div>\n'
        
        return stream | Transformer('//div[@id="ticket"]').append(MarkupTemplate(div).generate())

    # IRequestHandler methods
    def match_request(self, req):
        match = False
        if req.path_info == '/inform_update':
            match = True
        else:
            match = False
        return match

    # IRequestHandler methods
    def process_request(self, req):
        result = req.args.get('result')
        ticket = req.args.get('id')
        if result is None:
            self.outputJson(req, 'result:"false"')
            return
        if ticket is None:
            self.outputJson(req, 'result:"false"')
            return
        
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        
        sql = "SELECT yesuser,nouser FROM inform WHERE ticket=%s"
        cursor.execute(sql % (ticket))
        row = cursor.fetchone()
        if row is None:
            self.outputJson(req, 'result:"false"')
            return
        yesuser = row[0]
        nouser = row[1]
        if result.lower() in _TRUE_VALUES:
            yesuser = self.deleteUserList(yesuser, req.authname)
            nouser = self.addUserList(nouser, req.authname)
        else:
            yesuser = self.addUserList(yesuser, req.authname)
            nouser = self.deleteUserList(nouser, req.authname)

        sql = "UPDATE inform SET yesuser='%s',nouser='%s' WHERE ticket=%s"
        cursor.execute(sql % (yesuser, nouser, ticket))
        db.commit()

        self.outputJson(req, 'result:"true"')
    
    def addUserList(self, userdata, owner):
        if userdata == '':
            return owner
        
        user_list = userdata.split(',')
        existUser = False
        for user in user_list:
            if user == owner:
                existUser = True
        if existUser:
            return userdata
        else:
            return userdata + ',' + owner

    def deleteUserList(self, userdata, owner):
        if userdata == '':
            return ''
        user_list = userdata.split(',')
        result_list = ''
        for user in user_list:
            if user != owner:
                if result_list != '':
                    result_list = result_list + ','
                result_list = result_list + user
        return result_list
    
    def outputJson(self, req, data):
        response = json.dumps(data)
        req.send_response(200)
        req.send_header('Content-Type', 'application/json; charset=utf-8')
        req.send_header('Content-Length', len(response.encode("utf-8")))
        req.end_headers()
        req.write(response)

class InformVoteView(Component):
    implements(IRequestFilter, ITemplateStreamFilter, IRequestHandler)
    
    # IRequestFilter method
    def pre_process_request(self, req, handler):
        return handler
    
    # IRequestFilter method
    def post_process_request(self, req, template, content_type):
        return (template, content_type)
    
    # IRequestFilter method
    def post_process_request(self, req, template, data, content_type):
        if template == 'ticket.html':
            add_script(req, 'inform/js/inform_vote_view.js')

        return (template, data, content_type)
    
    # ITemplateStreamFilter method
    def filter_stream(self, req, method, filename, stream, data):
        if req.path_info.find('/ticket') != 0:
            return stream

        ticket = req.args.get('id')
        
        script = '\n<script type="text/javascript">\n'\
               + '$(function(){\n'\
               + '  inform_view("%s/inform_view","%s");\n' % (req.base_url, ticket) \
               + '});\n'\
               + '</script>\n'
        
        return stream | Transformer('//div[@id="footer"]').before(MarkupTemplate(script).generate())

    # IRequestHandler methods
    def match_request(self, req):
        match = False
        if req.path_info == '/inform_view':
            match = True
        else:
            match = False
        return match

    # IRequestHandler methods
    def process_request(self, req):
        
        ticket = req.args.get('id')
        inform_data = []
        if ticket is not None or ticket != '':
            inform_data = InformData(ticket, self.env)
            userlist = inform_data.getInformDb()

        response = json.dumps({"userlist": userlist})

        req.send_response(200)
        req.send_header('Content-Type', 'application/json; charset=utf-8')
        req.send_header('Content-Length', len(response.encode("utf-8")))

        req.end_headers()
        req.write(response)
