import libxml2 #;libxml2.debugMemory(1)
import libxslt

import jon.cgi as cgi
import jon.modpy as modpy

import Handler
from Handler import PATH_XML_DOCS
from Handler import PATH_XSL_DOCS

import os
import re
import commands
                
SELECT_VIEW_MUX_NONE = """
<div class="largegeneralcell" align="left">
    <label>Multiplexer logs:<br/>
        <select name="muxview" onchange="muxViewChange()">
            <option value="NULL" selected="selected"></option>
            <option value="mux_all">All Mux</option>
            <option value="mux_major">Major Mux</option>
            <option value="mux_info">Minor Mux</option>
        </select>
    </label>
</div>"""

SELECT_VIEW_MUX_ALL = """
<div class="largegeneralcell" align="left">
    <label>Multiplexer logs:<br/>
        <select name="muxview" onchange="muxViewChange()">
            <option value="NULL"></option>
            <option value="mux_all" selected="selected">All Mux</option>
            <option value="mux_major">Major Mux</option>
            <option value="mux_info">Minor Mux</option>
        </select>
    </label>
</div>"""

SELECT_VIEW_MUX_MAJ = """
<div class="largegeneralcell" align="left">
    <label>Multiplexer logs:<br/>
        <select name="muxview" onchange="muxViewChange()">
            <option value="NULL"></option>
            <option value="mux_all">All Mux</option>
            <option value="mux_major" selected="selected">Major Mux</option>
            <option value="mux_info">Minor Mux</option>
        </select>
    </label>
</div>"""

SELECT_VIEW_MUX_MIN = """
<div class="largegeneralcell" align="left">
    <label>Multiplexer logs:<br/>
        <select name="muxview" onchange="muxViewChange()">
            <option value="NULL"></option>
            <option value="mux_all">All Mux</option>
            <option value="mux_major">Major Mux</option>
            <option value="mux_info" selected="selected">Minor Mux</option>
        </select>
    </label>
</div>"""

SELECT_VIEW_OS_NONE = """
<div class="largegeneralcell" align="left">
    <label>OS logs:<br/>
        <select name="logsview" onchange="logsViewChange()">
            <option value="NULL" selected="selected"></option>
            <option value="all">all</option>
        </select>
    </label>
</div>"""


SELECT_VIEW_OS_ALL = """
<div class="largegeneralcell" align="left">
    <label>OS logs:<br/>
        <select name="logsview" onchange="logsViewChange()">
            <option value="NULL"></option>
            <option value="all" selected="selected">all</option>
        </select>
    </label>
</div>"""

BODY_START_PRETTY = """
          <table>
          <tr class="headerrow">
            <td class="idcell">ID</td>
            <td class="datecell">Date</td>
            <td class="timecell">Time</td>
            <td class="appcell">Application</td>
            <td class="sevcell">Severity</td>
            <td class="messagecell">Message</td>
          </tr>
"""
BODY_START_PLAIN = """
          <table>
          <tr class="headerrow">
            <td class="idcell">ID</td>
            <td class="messagecell">Log Message</td>
          </tr>
"""
MSG_NO_LOG = """
<div class="row"><div class="largegeneralcell">Log does not exist.</div></div>
"""
LOG_HTML_START_ID = """<tr class="activerow"><td class="idcell">"""
LOG_HTML_END_ID_START_PLAIN = """</td><td class="messagecell">"""
LOG_HTML_END_PLAIN = """</td></tr>"""
LOG_HTML_END_ID_START_DATE = """</td><td class="datecell">"""
LOG_HTML_END_DATE_START_TIME = """</td><td class="timecell">"""
LOG_HTML_END_TIME_START_APP = """</td><td class="appcell">"""
LOG_HTML_END_APP_START_EVENT_TYPE = """</td><td class="sevcell">"""
LOG_HTML_END_EVENT_TYPE_START_EVENT_MSG = """</td><td class="messagecell">"""
LOG_HTML_END_EVENT_MSG = """</td></tr>"""
LOG_HTML_END_TABLE = """</table>"""
LOG_HTML_FOOTER = """
      </div>
    </div>
  </body>
</html>
"""
_LOG_HTML_HEADER = """

"""
_BODY_START = """
                <center>
                        <table width="95%" border="0" cellspacing="0" cellpadding="0" align="center">
                            <tr>
                                <td>
                                    <table cellpadding="3" border="0">
                                        <tr>
                                            <td width="10" align="CENTER" nowrap background="../images/background.gif"><font face="Arial" size="-1" color="White"><b>Date</b></font></td>
                                            <td width="10" align="CENTER" nowrap background="../images/background.gif"><font face="Arial" size="-1" color="White"><b>Time</b></font></td>
                                            <td width="85" align="CENTER" nowrap background="../images/background.gif"><font face="Arial" size="-1" color="White"><b>Application</b></font></td>
                                            <td width="85" align="CENTER" nowrap background="../images/background.gif"><font face="Arial" size="-1" color="White"><b>Event Type</b></font></td>
                                            <td width="100%" align="CENTER" background="../images/background.gif"><font face="Arial" size="-1" color="White"><b>Event Message</b></font></td>
                                        </tr>
                                        <!-- Start here -->

"""

_LOG_HTML_START_DATE = """
<tr>
    <td valign="TOP" nowrap><font face="Arial" size="-2" color="White"><!-- Date Cell -->
"""

_LOG_HTML_END_DATE_START_TIME = """
    </font></td>
    <td valign="TOP" nowrap><font face="Arial" size="-2" color="White"><!-- Time Cell -->
"""
_LOG_HTML_END_TIME_START_APP = """
    </font></td>
    <td valign="TOP" nowrap><font face="Arial" size="-2" color="White"><!-- App Cell -->
"""

_LOG_HTML_END_APP_START_EVENT_TYPE = """
    </font></td>
    <td valign="TOP" nowrap><font face="Arial" size="-2" color="White"><!-- Event Type Cell -->
"""

_LOG_HTML_END_EVENT_TYPE_START_EVENT_MSG = """
    </font></td>
    <td valign="TOP"><font face="Arial" size="-2" color="White"><!-- Event Message Cell -->
"""

_LOG_HTML_END_EVENT_MSG = """
    </font></td>
</tr>
"""

_LOG_HTML_FOOTER = """
<!-- End of Log Data Entries -->
                                            </table>
                                        </td>
                                    </tr>
                                </table>
                            </center>
                        </td>
                    </tr>
                </table>
            </div>
        </div>
    </body>
</html>
"""

#LOG_TMP_PATH = '/var/tmp/log/'
LOG_PATH = '/var/log/'
ALL = 'all'
#AUTH = 'auth'
#CRON = 'cron'
#USER = 'user'
sz_buf = 8*1024
et = re.compile(r'\[.{,8}\]')

#def filterLines(lines, appMatch, evtTypeMatch):
#    for line in lines:
        
def processLine(rows, line, view, appMatch, evtTypeMatch, ID):
    if (len(line) > 1) and \
       (view == 'pretty'):
        # parse date, time, event type, event msg
        # line = formatted part + unformatted/multi-format part
        # formatted part = MMM DD HH:NN:SS
        #
        fmtPart = line[:16]
        unkPart = line[16:]
        dateStr = fmtPart[:6]
        timeStr = fmtPart[6:15]
        # parse app if exists
        app = ''
        idx = 0
        for ch in unkPart:
            if ch == ':':
                app = unkPart[:idx]
                break
            else:
                idx += 1
        if (len(app) <= 1):
            app = 'N/A'
        #evtType = 'TEST'
        evtMsg = unkPart[idx+1:]
        if (len(evtMsg) <= 1):
            evtMsg = unkPart
        m = et.search(evtMsg)
        if (m != None):
            evtType = m.group()[1:-1].strip()
            evtMsg = evtMsg[(m.end() + 1):]
        else:
            evtType = 'N/A'
            #evtMsg = unkPart
        #req.error('app=%s, appMatch=%s, evtTypeMatch=%s, evtType=%s\n' % (app, appMatch, evtTypeMatch, evtType))
        if ((((appMatch == '*') and (app != 'Edje3000')) or 
             (app.find(appMatch)>=0)) and ((evtTypeMatch == '*') or (evtTypeMatch == evtType))):
            rows.append(LOG_HTML_START_ID + '%d' + #repr(ID) +
                        LOG_HTML_END_ID_START_DATE + dateStr +
                        LOG_HTML_END_DATE_START_TIME + timeStr +
                        LOG_HTML_END_TIME_START_APP + app +
                        LOG_HTML_END_APP_START_EVENT_TYPE + evtType +
                        LOG_HTML_END_EVENT_TYPE_START_EVENT_MSG + cgi.html_encode(evtMsg).replace('%', '\%') +
                        LOG_HTML_END_EVENT_MSG
                        )
#            req.write(LOG_HTML_START_ID + repr(ID))
#            req.write(LOG_HTML_END_ID_START_DATE + dateStr)
#            req.write(LOG_HTML_END_DATE_START_TIME + timeStr)
#            req.write(LOG_HTML_END_TIME_START_APP + app)
#            req.write(LOG_HTML_END_APP_START_EVENT_TYPE + evtType)
#            req.write(LOG_HTML_END_EVENT_TYPE_START_EVENT_MSG + evtMsg)
#            req.write(LOG_HTML_END_EVENT_MSG)
            return 1
        return 0
    elif (len(line) > 1) and \
       (view == 'plain'):
        rows.append(LOG_HTML_START_ID + '%d' + #repr(ID) +
                    LOG_HTML_END_ID_START_PLAIN + cgi.html_encode(line) +
                    LOG_HTML_END_PLAIN
                    )
        return 1
    return 0

#class BufferedFileReverse:
#    def __init__():
#        pass
#    def _loadBuf():
#        pass
#    def getLine():
#        pass

class LogsHandler(Handler.Handler):
    
    _adminPage = 'logs.xsl'
    _roPage = 'rologs.xsl'
    
    def view(self, req):
        if self._xinclude:
            if self._muxconfig.xincludeProcess() == -1:
                self.traceback(req)
        pathXsl = self._pathXslDocs
        if pathXsl == None:
            pathXsl = PATH_XSL_DOCS
        if self._getState(req) == 'admin':
            styledoc = libxml2.parseFile(pathXsl + self._adminPage)
        else:
            styledoc = libxml2.parseFile(pathXsl + self._roPage)
        style = libxslt.parseStylesheetDoc(styledoc)
        style.parseStylesheetInclude(None)
        if self._message == None:
            xslDict = {'message':"''"}
        else:
            xslDict = {'message':"'" + self._message + "'"}

        # shovel any parameters into the stylesheet dict    
        if req.params.has_key("function"):
            xslDict.update({"function":"'"+req.params["function"]+"'"})     
        if req.params.has_key("destipaddr"):
            xslDict.update({"destipaddr":"'"+req.params["destipaddr"]+"'"})     
        if req.params.has_key("destport"):
            xslDict.update({"destport":"'"+req.params["destport"]+"'"})     
        if req.params.has_key("defaultsrcport"):
            xslDict.update({"srcport":"'"+req.params["defaultsrcport"]+"'"})     
        if req.params.has_key("defaultipttl"):
            xslDict.update({"defaultipttl":"'"+req.params["defaultipttl"]+"'"}) 
        xslDict.update({"hostname":"'"+self.getHostname()+"'"})
        result = style.applyStylesheet(self._muxconfig, xslDict)
        req.set_header('Content-Type', 'text/html')
        pageTop = style.saveResultToString(result)
        req.write(pageTop[:pageTop.find('<div id="putlogshere"')])
        result.freeDoc()
        result = None
        style.freeStylesheet()
        style = None
        styledoc = None
        
#        mux_app_name = self._muxconfig.xpathEval2('configuration/user_data/unit_name')[0].content
        #mux_app_name = 'asimux'
        # deal with paging
        if req.params.has_key('start_message'):
            logStartIdx = int(req.params['start_message'])
        else:
            logStartIdx = 0
        # deal with filtering
        select_view = SELECT_VIEW_MUX_NONE
        logs_select_view = SELECT_VIEW_OS_NONE
        if req.params.has_key('view_type'):
            viewtype = req.params['view_type']
        else:
            viewtype = 'pretty'
        if viewtype == 'pretty':
            if req.params.has_key('muxview'):
                view = req.params['muxview']
            else:
                view = 'mux_all'
        else:
            if req.params.has_key('logsview'):
                view = req.params['logsview']
            else:
                view = 'all'
        if view == '':
            view = 'mux_major'
        #tmpfname = LOG_TMP_PATH + USER
#        perfname = LOG_PATH + USER
        perfname = LOG_PATH + ALL
        #req.error('view = %s' %(view))
        # set defaults
        appMatch = '*'
        evtTypeMatch = '*'        
        #if view == 'mux_all':
        #    select_view = SELECT_VIEW_MUX_ALL
        #    appMatch = mux_app_name
        #    evtTypeMatch = '*'
        #elif view == 'mux_major':
        #    select_view = SELECT_VIEW_MUX_MAJ
        #    appMatch = mux_app_name
        #    evtTypeMatch = 'MAJOR'
        #elif view == 'mux_info':
        #    select_view = SELECT_VIEW_MUX_MIN
        #    appMatch = mux_app_name
        #    evtTypeMatch = 'INFO'
        #elif view == 'all':
        #    #tmpfname = LOG_TMP_PATH + view
        #     perfname = LOG_PATH + view
        #    logs_select_view = SELECT_VIEW_OS_ALL
        #if os.path.exists(tmpfname) or \
        if  os.path.exists(perfname):
            # get lines in reverse order
            lines = commands.getoutput('tac %s 2>/dev/null' % (perfname)).splitlines()
            accLines = len(lines)
            lineCount = 0
            rows = []
            if logStartIdx <= accLines and \
               logStartIdx >= 0:
#                for idx in range(accLines - logStartIdx, max((accLines - logStartIdx - 15), 0), -1):
                # filter out only the rows we want
                for idx in range(logStartIdx, min(logStartIdx+50, accLines), 1):
                    lineCount += processLine(rows, lines[idx], viewtype, appMatch, evtTypeMatch, lineCount)
                # start writing the page
                # begin form output
                START_FORM = '<form id="logControls" method="post" action="logs.py"><input type="hidden" name="view_type" value="%s"/><input type="hidden" name="start_message" id="start_message" value="%d"/><div class="row">' % (viewtype, logStartIdx)
                req.write(START_FORM)
                #req.write(select_view)
                FORM_INPUT = '<input type="image" name="submit" src="/images/submitquerybutton.gif" width="90" height="29" border="0"'            
                if ((logStartIdx - 50) >= 0):
                    Prev = '<a class="prevnextlink" href="javascript:PrevClick()">Prev</a>'
                else:
                    Prev = '<strike>Prev</strike>'
                if ((logStartIdx + 50) < accLines):
                     #Next = '<a class="prevnextlink" href="logs.py?muxview=' + view + '&start_message=' + str(logStartIdx +15) + '">Next</a>'
                    Next = '<a class="prevnextlink" href="javascript:NextClick()">Next</a>'
                else:
                    Next = '<strike>Next</strike>'
                #req.write(logs_select_view)
                #req.write(FORM_INPUT)
                END_FORM = '</div><div class="row"><div class="header"></div></div></form>'
                req.write(END_FORM)
                req.write('<div class="mediumcell">' + Prev + ' | ' + Next + '<br/>Viewing %d-%d of %d</div><br/>' % (logStartIdx+1, min(logStartIdx+50, accLines), accLines))
                if viewtype == 'pretty':
                    req.write(BODY_START_PRETTY)
                else:
                    req.write(BODY_START_PLAIN)
                # write all the rows
                for idx in range(0, len(rows), 1):
                    try:
                        req.write(rows[idx] % (logStartIdx+idx+1))
                    except:
                        req.error(rows[idx])
                        
                # finish the page
                req.write(LOG_HTML_END_TABLE)
                req.write(LOG_HTML_FOOTER)
        else:
            START_FORM = '<form id="logControls" method="post" action="logs.py"><div class="row"><input type="hidden" name="view_type" value="%s"/><input type="hidden" name="start_message" id="start_message" value="%d"/>' % (viewtype, logStartIdx)
            req.write(START_FORM)
            req.write(select_view)
            FORM_INPUT = '<div class="smallgeneralcell"><input type="image" name="submit" src="/images/submitquerybutton.gif" width="90" height="29" border="0"></div>'            
            req.write(logs_select_view)
            END_FORM = '</div><div class="row"><div class="header"><br/></div></div></form>'
            req.write(END_FORM)
            req.write(MSG_NO_LOG)
            if viewtype == 'pretty':
                req.write(BODY_START_PRETTY)
            else:
                req.write(BODY_START_PLAIN)
                req.write(LOG_HTML_END_TABLE)
            req.write(LOG_HTML_FOOTER)
        
                  
def handler(modpy_request):
    return modpy.Request(LogsHandler).process(modpy_request)
