import os
import time
from datetime import datetime, tzinfo, timedelta
from urlparse import urlsplit

from tram.util import get_project_list, get_allenv, prepare_request, debug, get_parent_href

from trac.core import *
from trac.web.api import *
from trac.web.chrome import add_stylesheet
from trac.web.clearsilver import HDFWrapper
from trac.web.href import Href

from trac.wiki.web_ui import WikiModule
from trac.util.text import to_unicode
from trac.util.datefmt import *

from trac.web.main import populate_hdf, open_environment, get_environments
from trac.web.main import RequestDispatcher
from trac.web.session import Session

def activity_cmp(x, y):
    if x['stats.score_month'] == y['stats.score_month']:
        return y['stats.score'] - x['stats.score']

    return y['stats.score_month'] - x['stats.score_month']

def send_project_index(environ, start_response, parent_dir=None,
                       env_paths=None, authname='anonymous'):

    req = Request(environ, start_response)
    req.authname = authname;
    if not req.authname:
        req.authname = "anonymous"

    loadpaths = []
    if req.environ.get('trac.env_index_template'):
        tmpl_path, template = os.path.split(req.environ['trac.env_index_template'])
        loadpaths.insert(0, tmpl_path)
    else:
        template = 'index.html'
    req.hdf = HDFWrapper(loadpaths)

    tmpl_vars = {}
    if req.environ.get('trac.template_vars'):
        for pair in req.environ['trac.template_vars'].split(','):
            key, val = pair.split('=')
            req.hdf[key] = val

    if parent_dir and not env_paths:
        env_paths = dict([(filename, os.path.join(parent_dir, filename))
                          for filename in os.listdir(parent_dir)])

    chrome = prepare_request(req, environ)

    config = get_allenv(environ, req).config
    need_auth = config.get('tram', 'check_auth') == 'true'
    auth_perm = config.get('tram', 'permission') or 'PROJECT_ACCESS'
    bar_color = config.get('tram', 'bar_color') or '#0b0'
    expand = config.get('tram', 'expand') or 'true'
    show_tickets_in_project_list = config.get('tram', 'show_tickets_in_project_list') or 'false'
    projects = get_project_list(environ, get_parent_href(req), authname=req.authname, require_auth=need_auth, permission=auth_perm)


    # Very simple method for calculating project activity
    # needs to be more advanced, tickets closed etc and per month not overall
    stop = time.time()
    t = time.localtime()
    start = time.mktime((t[0], t[1] - 1, t[2], t[3], t[4], t[5], t[6], t[7], t[8]))
    stop2 = int(stop)
    start2 = int(start)
    start = datetime(t[0], t[1], t[2], t[3], t[4], t[5], t[6], tzinfo=utc) - timedelta(30)
    stop  = datetime(t[0], t[1], t[2], t[3], t[4], t[5], t[6], tzinfo=utc)

    changes = 0
    changes_month = 0
    max_ticket = 0
    max_ticket_closed = 0
    max_ticket_month = 0
    max_ticket_closed_month = 0
    for project in projects:
        if not project.has_key('env'):
            continue;

        env = project['env']
        revisions = 0
        try:
            repos = env.get_repository(req.authname)
            #change_list = repos.get_changesets(start, stop)

            try:
              for chgset in repos.get_changesets(start, stop):
              #while change_list.next():
                  try:
                    revisions += 1
                  except Exception, e:
                    debug(to_unicode(e))
            except Exception, e:
              debug(to_unicode(e))

            changes_month = max(changes_month, revisions)

            try:
                total_revisions = int(repos.get_youngest_rev())
            except TypeError:
                total_revisions = 0
            changes = max(changes, total_revisions)
        except TracError ,e:
            total_revisions = 0
        except Exception, e:
            total_revisions = 0

        project['stats.changes_month'] = revisions
        project['stats.changes'] = total_revisions
        
        db = env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute("SELECT count(*) FROM ticket")
        for count, in cursor:
            project['stats.tickets'] = int(count)
        max_ticket = max(max_ticket, project['stats.tickets'])

        cursor = db.cursor()
        cursor.execute("SELECT count(*) FROM ticket_change WHERE field='status' AND newvalue='closed'")
        for count, in cursor:
            project['stats.tickets_closed'] = int(count)
        cursor = db.cursor()
        cursor.execute("SELECT count(*) FROM ticket_change WHERE field='status' AND newvalue='reopened'")
        for count, in cursor:
            project['stats.tickets_closed'] = int(project['stats.tickets_closed'] - count)
        max_ticket_closed = max(max_ticket_closed, project['stats.tickets_closed'])

        cursor = db.cursor()
        cursor.execute("SELECT count(*) FROM ticket WHERE time>=%s AND time<=%s" % (start2, stop2))
        for count, in cursor:
            project['stats.tickets_month'] = int(count)
        max_ticket_month = max(max_ticket_month, project['stats.tickets_month'])

        cursor = db.cursor()
        cursor.execute("SELECT count(*) FROM ticket_change WHERE field='status' AND newvalue='closed' AND time>=%s AND time <=%s" % (start2, stop2))
        for count, in cursor:
            project['stats.tickets_closed_month'] = int(count)
        cursor = db.cursor()
        cursor.execute("SELECT count(*) FROM ticket_change WHERE field='status' AND newvalue='reopened' AND time>=%s AND time <=%s" % (start2, stop2))
        for count, in cursor:
            project['stats.tickets_closed_month'] = int(project['stats.tickets_closed_month'] - count)
        max_ticket_closed_month = max(max_ticket_closed_month, project['stats.tickets_closed_month'])

    total = changes + max_ticket + max_ticket_closed
    if total == 0:
        ratio = 0
    else:
        ratio = 100.0 / float(total)
    
    total_month = changes_month + max_ticket_month + max_ticket_closed_month
    if total_month == 0:
        ratio_month = 0
    else:
        ratio_month = 100.0 / float(total_month)

    for project in projects:
        if not project.has_key('env'):
            project['stats.score_month'] = -999
            project['stats.score'] = -999
        else:
            project['stats.score_month'] = int(float(project['stats.changes_month'] + project['stats.tickets_month'] + project['stats.tickets_closed_month']) * ratio_month)
            percent = float(project['stats.changes'] + project['stats.tickets'] + project['stats.tickets_closed']) * ratio
            project['stats.score'] = int(percent)

    # Order output by activity
    projects.sort(activity_cmp)

    data = {}
    data['projects'] = projects
    data['bar_color'] = bar_color
    data['expand'] = expand
    data['show_tickets_in_project_list'] = show_tickets_in_project_list;
    data["chrome.nav.mainnav.projects.active"] = 1

    #add_stylesheet(req, "tram/css/project-list.css")

    # Default to the standard Tram clearsilver first
    templateFileName = "project_list.html"
    fullTemplatePath = os.path.dirname( __file__ ) + "/templates/" + templateFileName

    # Now override, if user has defined a custom one in their environment's templates dir
    customTemplateFile = get_allenv(environ, req).get_templates_dir() + "/" + templateFileName
    if os.path.isfile(customTemplateFile):
        fullTemplatePath = customTemplateFile

    chrome.populate_data(req, data)
    output = chrome.render_template(req, fullTemplatePath, data)
    req.session.save()
    req.send(output, 'text/html')

def send_project_index_old_style(environ, start_response, parent_dir=None,
                       env_paths=None, authname='anonymous'):

    req = Request(environ, start_response)
    req.authname = authname;

    loadpaths = []
    if req.environ.get('trac.env_index_template'):
        tmpl_path, template = os.path.split(req.environ['trac.env_index_template'])
        loadpaths.insert(0, tmpl_path)
    else:
        template = 'index.html'
    req.hdf = HDFWrapper(loadpaths)

    tmpl_vars = {}
    if req.environ.get('trac.template_vars'):
        for pair in req.environ['trac.template_vars'].split(','):
            key, val = pair.split('=')
            req.hdf[key] = val

    if parent_dir and not env_paths:
        env_paths = dict([(filename, os.path.join(parent_dir, filename))
                          for filename in os.listdir(parent_dir)])

    chrome = prepare_request(req, environ)

    config = get_allenv(environ, req).config
    need_auth = config.get('tram', 'check_auth') == 'true'
    auth_perm = config.get('tram', 'permission') or 'PROJECT_ACCESS'
    projects = get_project_list(environ, get_parent_href(req), authname=req.authname, require_auth=need_auth, permission=auth_perm)

    data = {}
    data['projects'] = projects
    data["chrome.nav.mainnav.projects.active"] = 1

    # Default to the standard Tram clearsilver first
    templateFileName = "project_list_old_style.html"
    fullTemplatePath = os.path.dirname( __file__ ) + "/templates/" + templateFileName

    # Now override, if user has defined a custom one in their environment's templates dir
    customTemplateFile = get_allenv(environ, req).get_templates_dir() + "/" + templateFileName
    if os.path.isfile(customTemplateFile):
        fullTemplatePath = customTemplateFile

    chrome.populate_data(req, data)
    output = chrome.render_template(req, fullTemplatePath, data)
    req.session.save()
    req.send(output, 'text/html')

def send_search_index(environ, start_response, parent_dir=None,
                       env_paths=None, authname='anonymous'):

    req = Request(environ, start_response)
    req.authname = authname;

    loadpaths = []
    if req.environ.get('trac.env_index_template'):
        tmpl_path, template = os.path.split(req.environ['trac.env_index_template'])
        loadpaths.insert(0, tmpl_path)
    else:
        template = 'index.html'
    req.hdf = HDFWrapper(loadpaths)

    tmpl_vars = {}
    if req.environ.get('trac.template_vars'):
        for pair in req.environ['trac.template_vars'].split(','):
            key, val = pair.split('=')
            req.hdf[key] = val

    if parent_dir and not env_paths:
        env_paths = dict([(filename, os.path.join(parent_dir, filename))
                          for filename in os.listdir(parent_dir)])

    chrome = prepare_request(req, environ)

    config = get_allenv(environ, req).config
    need_auth = config.get('tram', 'check_auth') == 'true'
    auth_perm = config.get('tram', 'permission') or 'PROJECT_ACCESS'
    parent_href = get_parent_href(req)
    projects = get_project_list(environ, parent_href, authname=req.authname, require_auth=need_auth, permission=auth_perm)

    data = {}
    data['projects'] = projects
    data["chrome.nav.mainnav.search.active"] = 1
    data["base_url"] = urlsplit(parent_href())[2] + "/"

    # Default to the standard Tram clearsilver first
    templateFileName = "search_index.html"
    fullTemplatePath = os.path.dirname( __file__ ) + "/templates/" + templateFileName

    # Now override, if user has defined a custom one in their environment's templates dir
    customTemplateFile = get_allenv(environ, req).get_templates_dir() + "/" + templateFileName
    if os.path.isfile(customTemplateFile):
        fullTemplatePath = customTemplateFile

    chrome.populate_data(req, data)
    output = chrome.render_template(req, fullTemplatePath, data)
    req.session.save()
    req.send(output, 'text/html')


