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

import re
import sys
import time

from trac.perm import PermissionError, PermissionSystem
from trac.resource import ResourceNotFound
from trac.ticket.model import Ticket
from trac.ticket.notification import TicketNotifyEmail
from trac.util.compat import set
from trac.util.text import console_print
from trac.web.chrome import Chrome

from genshi.builder import tag
from genshi.template.markup import MarkupTemplate

def atomic_id():
    return str(time.time()).replace('.', '')

def template(env, template, data={}, method="xhtml"):
    from trac.web.chrome import Chrome
    template = Chrome(env).load_template(template, method=method)
    result = template.generate(**data)
    return result

def to_localdate(utcdate, zoneoffset):
    return time.strftime("%Y/%m/%d %H:%M:%S", time.gmtime(utcdate + zoneoffset))

def get_mlperm_action(mlid):
    return u'MAILARCHIVE_VIEW_%s' % mlid.upper()

def get_accessable_ml(env, req, ml_permission_map):
    perm = PermissionSystem(env)
    actions = perm.get_user_permissions(req.authname)
    view_actions = [x for x in actions if x.startswith('MAILARCHIVE_VIEW_')]
    accessable_mlids = [ml_permission_map.get(x) for x in view_actions]
    return view_actions, accessable_mlids

def has_mailarchive_view_permission(env, req):
    if 'MAILARCHIVE_VIEW' in req.perm('mailarchive'):
        return True
    
    perm = PermissionSystem(env)
    actions = perm.get_user_permissions(req.authname)
    view_actions = [x for x in actions if x.startswith('MAILARCHIVE_VIEW_')]

    if len(view_actions) > 0:
        return True
    else:
        return False
    
def linkify_id(env, req, id=None, mail=None):
    from model import Mail
    try:
        m = None
        if mail:
            m = mail
        else:
            try:
                m = Mail(env, id)
            except ValueError:
                return id
        m.assert_permission(req)
        link = tag.a('mail:%s' % m.id,
                     href=req.href.mailarchive(m.id),
                     class_='ticket',
                     title='%s %s %s' % (m.get_fromtext(), m.get_senddate(), m.subject))
        return link
    except (ResourceNotFound, PermissionError), e:
        return id

def linkify_ids(env, req, ids):
    if len(ids) == 0 or ids[0] == '':
        return tag.span()
    
    data = []
    
    from model import MailFinder
    mails = MailFinder.find_mails(env, ids)
    
    for mail in sorted(mails, key=lambda x: int(x.id)):
        data.append(linkify_id(env, req, mail=mail))
        data.append(', ')
    if data:
        del data[-1] # Remove the last comma if needed
    return tag.span(*data)

def to_mail_ids(mail_id_plain):
    mail_ids = []
    if mail_id_plain is None:
        mail_ids = []
    else:
        for mail_id in mail_id_plain.split(','):
            try:
                id = int(mail_id.strip())
                mail_ids.append(str(id))
            except ValueError:
                continue
    return mail_ids
            
def get_author(fromname, fromaddr):
    author = fromname
    if fromname == '':
        if re.match('(.+?)@', fromaddr):
            author = re.match('(.+?)@', fromaddr).group(1)
    if author == None or author.strip() == '':
        author = '--'
    return author

def get_all_users(env):
    """return the names of all known users in the trac environment"""
    return [i[0] for i in env.get_known_users()]

def get_login_email(env, req):
    tn = TicketNotifyEmail(env)
    return tn.email_map.get(req.authname, 'unknown')

def get_email(env, username):
    tn = TicketNotifyEmail(env)
    return tn.email_map.get(username, 'unknown')

def get_related_ticket_ids(env, req, db, mail_id):
    # cached?
    if not hasattr(req, '_mailarchive_related_ticket_map'):
        cursor = db.cursor()
        
        sql = """SELECT ticket, value
        FROM ticket_custom
        WHERE name='mail_id' AND value <> ''"""
        
        cursor.execute(sql)
        
        related_ticket_map = {}
        
        for ticket_id, mail_ids in cursor:
            mail_ids = [x.strip() for x in mail_ids.split(',') if x.strip() != '']
            for mid in mail_ids:
                try:
                    mid = str(int(mid))
                    ticket_ids = related_ticket_map.get(mid, set())
                    ticket_ids.add(str(ticket_id))
                    related_ticket_map.update({mid:ticket_ids})
                except ValueError:
                    env.log.warn("#%s ticket has invalid mail_id [%s]" % (str(ticket_id), str(mid)))
                    continue
        
        req._mailarchive_related_ticket_map = related_ticket_map
        
    related_ticket_map = req._mailarchive_related_ticket_map
    return related_ticket_map.get(str(mail_id), [])
    
def get_related_tickets(env, req, db, mail_id):
    ticket_ids = get_related_ticket_ids(env, req, db, mail_id)
    
    tickets = []
    for ticket_id in ticket_ids:
        tickets.append(Ticket(env, ticket_id))
        
    return tickets

def get_all_related_tickets(env, req, db, mail):
    thread_mails = mail.get_thread_mails()
    thread_root = mail.get_thread_root()
    thread_mails.append(thread_root)
    
    related_tickets = set()
    for thread_mail in thread_mails:
        ticket_ids = get_related_ticket_ids(env, req, db, thread_mail.id)
        related_tickets.update(ticket_ids)
    return related_tickets

def get_category_href(req, category):
    return req.href.mailarchive() + '?category=%s' % category

def get_item_per_page(env):
    return int(env.config.get('mailarchive', 'items_page','50'))

def get_num_shown_pages(env):
    return int(env.config.get('mailarchive', 'shown_pages','30'))

def month_add(year, month, add_month):
    month = month + add_month
    while month >12 or month <1:
        if month > 12:
            month = month - 12
            year = year + 1
        else :
            month = month + 12
            year = year - 1
        
def is_empty(str):
    return str == None or str.strip() == ''
    
def printout(*args):
    console_print(sys.stdout, *args)

def printerr(*args):
    console_print(sys.stderr, *args)
    
class Logger:
    
    def __init__(self, env):
        try:
            self.log = env.log
        except AttributeError:
            self.log = None
            
    def debug(self, *args):
        if self.log:
            self.log.debug(*args)
        else:
            printout(*args)
            
    def info(self, *args):
        if self.log:
            self.log.info(*args)
        else:
            printout(*args)
            
    def warn(self, *args):
        if self.log:
            self.log.warn(*args)
        else:
            printout(*args)
    
    def error(self, *args):
        if self.log:
            self.log.error(*args)
        else:
            printerr(*args)
        

