# -*- coding: utf-8 -*-
from trac.ticket import ITicketChangeListener, Ticket, ITicketManipulator
from trac.config import Option
from trac.core import *
import datetime

class CompleteTicketObserver(Component):
    implements(ITicketChangeListener)

    complete_conditions = Option('ganttcalendar', 'complete_conditions', 'fixed, invalid', u"""티켓을 close할 때, 진척율을 100%로 자동 변경할 해결방법들(Resolutions)을 설정합니다.""")
    complete_field = Option('ganttcalendar', 'complete_field', 'complete', u"""진척율(complete) 설정 필드""")

    def __init__(self):
        pass

    def ticket_created(self, ticket):
        """Called when a ticket is created."""
        self.watch_complete(ticket)

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

        `old_values` is a dictionary containing the previous values of the
        fields that have changed.
        """
        self.watch_complete(ticket, old_values)

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


    def watch_complete(self, ticket, old_values={}):

        def readTicketValue(field, default=''):
            # for UPDATE: save_ticket_change
            if old_values.has_key(field):
                return old_values[field]
            # for INSERT: save_ticket_change
            else:
                cursor = self.env.get_db_cnx().cursor()
                cursor.execute("SELECT * FROM ticket_custom where ticket=%s and name=%s" , (ticket.id, field))
                val = cursor.fetchone()
                if val:
                    return val[2]
                return default
        ########################

        def writeTicketValue(field, oldvalue, newvalue):
            cl = ticket.get_changelog()
            if cl: # for ticket_changed
                most_recent_change = cl[-1];
                change_time = most_recent_change[0]
                author = most_recent_change[1]
            else:  # for ticket_created
                change_time = ticket.time_created
                author = ticket.values["reporter"]
            self.log.debug("oldvalue: '%s', newvalue: '%s'" % (oldvalue, newvalue))
            #self.log.debug("changelog: %s" % cl)
            db = self.env.get_db_cnx()
            if cl:
                save_ticket_change( db, ticket.id, author, change_time, field, oldvalue, newvalue, self.log)
            save_custom_field_value( db, ticket.id, field, newvalue)
            db.commit();
        ########################


        complete_field = self.config['ganttcalendar'].get('complete_field', default='complete') or 'complete'
        due_assign = ticket.values.get('due_assign')
        due_close  = ticket.values.get('due_close')
        complete   = ticket.values.get(complete_field)
        #self.log.debug("ticket.values: %s" % ticket.values)

        if not (due_assign or due_close) or (complete == None):
            return;

        oldstatus  = old_values.get('status')
        status     = ticket.values.get('status')
        resolution = ticket.values.get('resolution')
        complete_conditions = self.config['ganttcalendar'].getlist('complete_conditions', default='fixed, invalid')
        self.log.debug("oldstatus: %s, status: %s, resolution: %s, complete_conditions: %s" % (oldstatus, status, resolution, complete_conditions))

        # complete by close
        if (status == 'closed' and oldstatus) \
          and resolution in complete_conditions:
            writeTicketValue( complete_field, readTicketValue(complete_field), '100')
        # initial value
        elif complete == '':
            writeTicketValue( complete_field, readTicketValue(complete_field), '0')

    ########################


def identity(x):
    return x;

try:
    from trac import __version__
    import trac.util.datefmt
    if __version__ < '0.12':
        to_timestamp = trac.util.datefmt.to_timestamp
    else:
        to_timestamp = trac.util.datefmt.to_utimestamp
except Exception:
    to_timestamp = identity

def save_custom_field_value( db, ticket_id, field, value ):
    cursor = db.cursor()
    cursor.execute("SELECT * FROM ticket_custom "
                   "WHERE ticket=%s and name=%s", (ticket_id, field))
    if cursor.fetchone():
        cursor.execute("UPDATE ticket_custom SET value=%s "
                       "WHERE ticket=%s AND name=%s",
                       (value, ticket_id, field))
    else:
        cursor.execute("INSERT INTO ticket_custom (ticket,name, "
                       "value) VALUES(%s,%s,%s)",
                       (ticket_id, field, value))

DONTUPDATE = "DONTUPDATE"

def save_ticket_change( db, ticket_id, author, change_time, field, oldvalue, newvalue, log, dontinsert=False):
    """tries to save a ticket change,

       dontinsert means do not add the change if it didnt already exist
    """
    if type(change_time) == datetime.datetime:
        change_time = to_timestamp(change_time)
    cursor = db.cursor();
    sql = """SELECT * FROM ticket_change
             WHERE ticket=%s and author=%s and time=%s and field=%s"""

    cursor.execute(sql, (ticket_id, author, change_time, field))
    if cursor.fetchone():
        if oldvalue == DONTUPDATE:
            cursor.execute("""UPDATE ticket_change  SET  newvalue=%s
                       WHERE ticket=%s and author=%s and time=%s and field=%s""",
                           ( newvalue, ticket_id, author, change_time, field))

        else:
            cursor.execute("""UPDATE ticket_change  SET oldvalue=%s, newvalue=%s
                       WHERE ticket=%s and author=%s and time=%s and field=%s""",
                           (oldvalue, newvalue, ticket_id, author, change_time, field))
    else:
        if oldvalue == DONTUPDATE:
            oldvalue = '0'
        if not dontinsert:
            cursor.execute("""INSERT INTO ticket_change  (ticket,time,author,field, oldvalue, newvalue)
                        VALUES(%s, %s, %s, %s, %s, %s)""",
                           (ticket_id, change_time, author, field, oldvalue, newvalue))
