# w.c.s. - web application for online forms
# Copyright (C) 2005-2010  Entr'ouvert
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.

import os
import random

from quixote import get_publisher, get_request, get_response
from quixote.html import htmltext, TemplateIO
from quixote.directory import Directory

from .. import _
from .. import logger, errors
from ..backoffice.menu import html_top
from ..admin.menu import error_page

class ByUserDirectory(Directory):
    def _q_lookup(self, component):
        return ByUserPages(component)


class LoggerDirectory(Directory):
    _q_exports = ['', 'download', 'by_user']

    by_user = ByUserDirectory()

    def _q_index(self):
        get_response().breadcrumb.append(('logs/', _('Logs')))
        html_top('logs', title=_('Logs'))
        r = TemplateIO(html=False)
        request = get_request()
        logfile = str(request.get_field('logfile', get_publisher().APP_NAME + '.log'))
        if not logfile.startswith(str(get_publisher().APP_NAME + '.log')) or str('/') in str(logfile):
            return error_page('logs/', _('Bad log file: %s') % logfile)
        logfilename = str(os.path.join(get_publisher().app_dir, logfile))

        if not os.path.exists(logfilename):
            r += _('Nothing to show')
        else:
            get_response().filter['sidebar'] = self.get_sidebar(logfile)

            user_color_keys = {}
            last_date = None
            r += htmltext('<table id="logs">\n')
            r += htmltext('<thead> <tr>')
            r += htmltext(' <th>%s</th>') % _('Time')
            r += htmltext(' <th>%s</th>') % _('User')
            r += htmltext(' <th>%s</th>') % _('Message')
            r += htmltext('<tr></thead>\n')
            r += htmltext('<tbody>\n')
            i = 1
            userlabels = {}
            for d in logger.parse_logstream(open(logfilename)):
                if not d:
                    continue

                if d.get('user_id'):
                    user_color_key = d['user_id']
                    if user_color_key == 'anonymous':
                        user_color_key += d['ip']
                    if user_color_key not in user_color_keys:
                        user_color_keys[user_color_key] = ''.join(
                            ['%x' % random.randint(0xc, 0xf) for x in range(3)])
                    r += htmltext('<tr class="level-%s" style="background: #%s;">') % (
                            d['level'].lower(), user_color_keys[user_color_key])
                else:
                    r += htmltext('<tr class="level-%s">') % d['level'].lower()

                if last_date != d['date']:
                    r += htmltext(' <td class="time">%s&nbsp;%s</td>') % (d['date'], d['hour'][:-4])
                    last_date = d['date']
                else:
                    r += htmltext(' <td class="time">%s</td>') % (d['hour'][:-4])

                user_id = d.get('user_id')
                if not user_id:
                    userlabel = None
                elif user_id == 'anonymous':
                    userlabel = _('Anonymous')
                    ip = d['ip']
                    r += htmltext(' <td class="userlabel"><span title="%s">%s</span></td>') % (ip, userlabel)
                elif user_id == 'unlogged':
                    userlabel = _('Unlogged')
                    ip = d['ip']
                    r += htmltext(' <td class="userlabel"><span title="%s">%s</span></td>') % (ip, userlabel)
                elif user_id == 'bot':
                    userlabel = _('Bot')
                    r += htmltext(' <td class="userlabel">%s</td>') % userlabel
                else:
                    userlabel = userlabels.get(user_id)
                    if not userlabel:
                        try:
                            user = get_publisher().user_class.get(user_id)
                            userlabel = htmltext(user.display_name.replace(str(' '), str('&nbsp;')))
                        except KeyError:
                            userlabel = _('Unknown')
                        userlabels[user_id] = userlabel
                    r += htmltext(' <td class="userlabel">%s</td>') % userlabel
                if userlabel:
                    r += htmltext(' <td class="message">%s</td>') % d['message']
                else:
                    r += htmltext('<td class="message" colspan="2">%s</td>') % d['message']
                r += htmltext('</tr>\n')
            r += htmltext('</tbody>\n')
            r += htmltext('</table>\n')
        return r.getvalue()

    def get_sidebar(self, logfile):
        r = TemplateIO(html=True)
        r += htmltext('<ul>')
        if logfile:
            r += htmltext('<li><a href="download?logfile=%s">%s</a></li>') % (logfile, _('Download Raw Log File'))
        else:
            r += htmltext('<li><a href="download">%s</a></li>') % _('Download Raw Log File')
        r += htmltext('</ul>')

        logfiles = [x for x in os.listdir(get_publisher().app_dir) if x.startswith(get_publisher().APP_NAME + str('.log'))]
        if len(logfiles) > 1:
            options = []
            for lfile in logfiles:
                firstline = open(os.path.join(get_publisher().app_dir, lfile)).readline()
                d = logger.readline(firstline)
                if not d:
                    continue
                if logfile == lfile:
                    selected = 'selected="selected" '
                else:
                    selected = ''
                options.append({'selected': selected, 'lfile': lfile,
                        'date': '%s %s' % (d['date'], d['hour'])})

            r += htmltext('<form id="other-log-select">')
            r += _('Select another logfile:')
            r += htmltext('<select name="logfile">')
            options.sort(lambda x,y: cmp(x['date'], y['date']))
            options.reverse()
            for option in options:
                option['since'] = str(_('Since: %s') % option['date'])[:-4]
                r += htmltext('<option value="%(lfile)s"%(selected)s>%(since)s</option>') % option
            r += htmltext('</select>')
            r += htmltext('<input type="submit" value="%s" />') % _('Submit')

        return r.getvalue()


    def download(self):
        request = get_request()
        logfile = request.get_field('logfile', get_publisher().APP_NAME + '.log')
        if not logfile.startswith(get_publisher().APP_NAME + '.log') or str('/') in logfile:
            return error_page('logs/', _('Bad log file: %s') % logfile)
        logfilename = os.path.join(get_publisher().app_dir, logfile)
        response = get_response()
        response.set_content_type('text/x-log', 'iso-8859-1')
        response.set_header('content-disposition', 'attachment; filename=%s' % logfile)
        return open(logfilename).read()


class ByUserPages(Directory):
    _q_exports = ['']

    def __init__(self, component):
        try:
            self.user = get_publisher().user_class.get(component)
        except KeyError:
            raise errors.TraversalError()

    def _q_index(self):
        html_top('logs', title=_('Logs'))
        r = TemplateIO(html=True)
        r += htmltext('<h2>%s - %s</h2>') % (_('User'), self.user.name)

        last_date = None
        r += htmltext('<table id="logs">')
        r += htmltext('<thead> <tr>')
        r += htmltext(' <th>%s</th>') % _('Time')
        r += htmltext(' <th>%s</th>') % _('Message')
        r += htmltext('<tr></thead>')
        r += htmltext('<tbody>')
        logfilename = str(os.path.join(get_publisher().app_dir, get_publisher().APP_NAME + '.log'))
        if os.path.exists(logfilename):
            for line in open(logfilename):
                d = logger.readline(line)
                if not d or d['user_id'] != str(self.user.id):
                    continue
                r += htmltext('<tr>')
                if last_date != d['date']:
                    r += htmltext(' <td class="time">%s&nbsp;%s</td>') % (d['date'], d['hour'][:-4])
                    last_date = d['date']
                else:
                    r += htmltext(' <td class="time">%s</td>') % (d['hour'][:-4])
                r += htmltext(' <td><a href="%s">%s</a></td>') % (d['url'], d['message'])
                r += htmltext('</tr>')
        r += htmltext('</tbody>')
        r += htmltext('</table>')
        return r.getvalue()
