import BaseHTTPServer
import SimpleHTTPServer
import os
import sys
import urllib, urlparse
import posixpath
import StringIO
import re
import shutil
import threading
import time
import socket
import itertools

import Reporter
import ConfigParser

###
# Various patterns matched or replaced by server.

kReportFileRE = re.compile('(.*/)?report-(.*)\\.html')

kBugKeyValueRE = re.compile('<!-- BUG([^ ]*) (.*) -->')

#  <!-- REPORTPROBLEM file="crashes/clang_crash_ndSGF9.mi" stderr="crashes/clang_crash_ndSGF9.mi.stderr.txt" info="crashes/clang_crash_ndSGF9.mi.info" -->

kReportCrashEntryRE = re.compile('<!-- REPORTPROBLEM (.*?)-->')
kReportCrashEntryKeyValueRE = re.compile(' ?([^=]+)="(.*?)"')

kReportReplacements = []

# Add custom javascript.
kReportReplacements.append((re.compile('<!-- SUMMARYENDHEAD -->'), """\
<script language="javascript" type="text/javascript">
function load(url) {
  if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    req = new ActiveXObject("Microsoft.XMLHTTP");
  }
  if (req != undefined) {
    req.open("GET", url, true);
    req.send("");
  }
}
</script>"""))

# Insert additional columns.
kReportReplacements.append((re.compile('<!-- REPORTBUGCOL -->'), 
                            '<td></td><td></td>'))

# Insert report bug and open file links.
kReportReplacements.append((re.compile('<!-- REPORTBUG id="report-(.*)\\.html" -->'),
                            ('<td class="Button"><a href="report/\\1">Report Bug</a></td>' + 
                             '<td class="Button"><a href="javascript:load(\'open/\\1\')">Open File</a></td>')))

kReportReplacements.append((re.compile('<!-- REPORTHEADER -->'),
                                       '<h3><a href="/">Summary</a> > Report %(report)s</h3>'))

kReportReplacements.append((re.compile('<!-- REPORTSUMMARYEXTRA -->'),
                            '<td class="Button"><a href="report/%(report)s">Report Bug</a></td>'))

# Insert report crashes link.

kReportReplacements.append((re.compile('<!-- REPORTCRASHES -->'),
                            '<br>These files will automatically be attached to ' +
                            'reports filed here: <a href="report_crashes">Report Crashes</a>.'))

###
# Other simple parameters

kResources = posixpath.join(posixpath.dirname(__file__), 'Resources')
kConfigPath = os.path.expanduser('~/.scanview.cfg')

###

__version__ = "0.1"

__all__ = ["create_server"]

class ReporterThread(threading.Thread):
    def __init__(self, report, reporter, parameters, server):
        threading.Thread.__init__(self)
        self.report = report
        self.server = server
        self.reporter = reporter
        self.parameters = parameters
        self.success = False
        self.status = None

    def run(self):
        result = None
        try:
            if self.server.options.debug:
                print >>sys.stderr, "%s: SERVER: submitting bug."%(sys.argv[0],)
            self.status = self.reporter.fileReport(self.report, self.parameters)
            self.success = True
            time.sleep(3)
            if self.server.options.debug:
                print >>sys.stderr, "%s: SERVER: submission complete."%(sys.argv[0],)
        except Reporter.ReportFailure,e:
            self.status = e.value
        except Exception,e:
            s = StringIO.StringIO()
            import traceback
            print >>s,'<b>Unhandled Exception</b><br><pre>'
            traceback.print_exc(e,file=s)
            print >>s,'</pre>'
            self.status = s.getvalue()

class ScanViewServer(BaseHTTPServer.HTTPServer):
    def __init__(self, address, handler, root, reporters, options):
        BaseHTTPServer.HTTPServer.__init__(self, address, handler)
        self.root = root
        self.reporters = reporters
        self.options = options        
        self.halted = False
        self.config = None
        self.load_config()

    def load_config(self):
        self.config = ConfigParser.RawConfigParser()

        # Add defaults
        self.config.add_section('ScanView')
        for r in self.reporters:
            self.config.add_section(r.getName())
            for p in r.getParameterNames():
                self.config.set(r.getName(), p, '')

        # Ignore parse errors
        try:
            self.config.read([kConfigPath])
        except:
            pass

        # Save on exit
        import atexit
        atexit.register(lambda: self.save_config())
        
    def save_config(self):
        # Ignore errors (only called on exit).
        try:
            f = open(kConfigPath,'w')
            self.config.write(f)
            f.close()
        except:
            pass
        
    def halt(self):
        self.halted = True
        if self.options.debug:
            print >>sys.stderr, "%s: SERVER: halting." % (sys.argv[0],)

    def serve_forever(self):
        while not self.halted:
            if self.options.debug > 1:
                print >>sys.stderr, "%s: SERVER: waiting..." % (sys.argv[0],)
            try:
                self.handle_request()
            except OSError,e:
                print 'OSError',e.errno

    def finish_request(self, request, client_address):
        if self.options.autoReload:
            import ScanView
            self.RequestHandlerClass = reload(ScanView).ScanViewRequestHandler
        BaseHTTPServer.HTTPServer.finish_request(self, request, client_address)

    def handle_error(self, request, client_address):
        # Ignore socket errors
        info = sys.exc_info()
        if info and isinstance(info[1], socket.error):
            if self.options.debug > 1:
                print >>sys.stderr, "%s: SERVER: ignored socket error." % (sys.argv[0],)
            return
        BaseHTTPServer.HTTPServer.handle_error(self, request, client_address)

# Borrowed from Quixote, with simplifications.
def parse_query(qs, fields=None):
    if fields is None:
        fields = {}
    for chunk in filter(None, qs.split('&')):
        if '=' not in chunk:
            name = chunk
            value = ''
        else:
            name, value = chunk.split('=', 1)
        name = urllib.unquote(name.replace('+', ' '))
        value = urllib.unquote(value.replace('+', ' '))
        item = fields.get(name)
        if item is None:
            fields[name] = [value]
        else:
            item.append(value)
    return fields

class ScanViewRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    server_version = "ScanViewServer/" + __version__
    dynamic_mtime = time.time()

    def do_HEAD(self):
        try:
            SimpleHTTPServer.SimpleHTTPRequestHandler.do_HEAD(self)
        except Exception,e:
            self.handle_exception(e)
            
    def do_GET(self):
        try:
            SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
        except Exception,e:
            self.handle_exception(e)
            
    def do_POST(self):
        """Serve a POST request."""
        try:
            length = self.headers.getheader('content-length') or "0"
            try:
                length = int(length)
            except:
                length = 0
            content = self.rfile.read(length)
            fields = parse_query(content)
            f = self.send_head(fields)
            if f:
                self.copyfile(f, self.wfile)
                f.close()
        except Exception,e:
            self.handle_exception(e)            

    def log_message(self, format, *args):
        if self.server.options.debug:
            sys.stderr.write("%s: SERVER: %s - - [%s] %s\n" %
                             (sys.argv[0],
                              self.address_string(),
                              self.log_date_time_string(),
                              format%args))

    def load_report(self, report):
        path = os.path.join(self.server.root, 'report-%s.html'%report)
        data = open(path).read()
        keys = {}
        for item in kBugKeyValueRE.finditer(data):
            k,v = item.groups()
            keys[k] = v
        return keys

    def load_crashes(self):
        path = posixpath.join(self.server.root, 'index.html')
        data = open(path).read()
        problems = []
        for item in kReportCrashEntryRE.finditer(data):
            fieldData = item.group(1)
            fields = dict([i.groups() for i in 
                           kReportCrashEntryKeyValueRE.finditer(fieldData)])
            problems.append(fields)
        return problems

    def handle_exception(self, exc):
        import traceback
        s = StringIO.StringIO()
        print >>s, "INTERNAL ERROR\n"
        traceback.print_exc(exc, s)
        f = self.send_string(s.getvalue(), 'text/plain')
        if f:
            self.copyfile(f, self.wfile)
            f.close()        
            
    def get_scalar_field(self, name):
        if name in self.fields:
            return self.fields[name][0]
        else:
            return None

    def submit_bug(self, c):
        title = self.get_scalar_field('title')
        description = self.get_scalar_field('description')
        report = self.get_scalar_field('report')
        reporterIndex = self.get_scalar_field('reporter')
        files = []
        for fileID in self.fields.get('files',[]):
            try:
                i = int(fileID)
            except:
                i = None
            if i is None or i<0 or i>=len(c.files):
                return (False, 'Invalid file ID')
            files.append(c.files[i])
        print files
        
        if not title:
            return (False, "Missing title.")
        if not description:
            return (False, "Missing description.")
        try:
            reporterIndex = int(reporterIndex)
        except:
            return (False, "Invalid report method.")
        
        # Get the reporter and parameters.
        reporter = self.server.reporters[reporterIndex]
        parameters = {}
        for o in reporter.getParameterNames():
            name = '%s_%s'%(reporter.getName(),o)
            if name not in self.fields:
                return (False, 
                        'Missing field "%s" for %s report method.'%(name,
                                                                    reporter.getName()))
            parameters[o] = self.get_scalar_field(name)

        # Update config defaults.
        if report != 'None':
            self.server.config.set('ScanView', 'reporter', reporterIndex)
            for o in reporter.getParameterNames():
                self.server.config.set(reporter.getName(), o, parameters[o])

        # Create the report.
        bug = Reporter.BugReport(title, description, files)

        # Kick off a reporting thread.
        t = ReporterThread(bug, reporter, parameters, self.server)
        t.start()

        # Wait for thread to die...
        while t.isAlive():
            time.sleep(.25)
        submitStatus = t.status

        return (t.success, t.status)

    def send_report_submit(self):
        print self.fields
        report = self.get_scalar_field('report')
        c = self.get_report_context(report)
        if c.reportSource is None:
            reportingFor = "Report Crashes > "
            fileBug = """\
<a href="/report_crashes">File Bug</a> > """%locals()
        else:
            reportingFor = '<a href="/%s">Report %s</a> > ' % (c.reportSource, 
                                                                   report)
            fileBug = '<a href="/report/%s">File Bug</a> > ' % report
        title = self.get_scalar_field('title')
        description = self.get_scalar_field('description')

        res,message = self.submit_bug(c)

        if res:
            statusClass = 'SubmitOk'
            statusName = 'Succeeded'
        else:
            statusClass = 'SubmitFail'
            statusName = 'Failed'

        result = """
<head>
  <title>Bug Submission</title>
  <link rel="stylesheet" type="text/css" href="/scanview.css" />
</head>
<body>
<h3>
<a href="/">Summary</a> > 
%(reportingFor)s
%(fileBug)s
Submit</h3>
<form name="form" action="">
<table class="form">
<tr><td>
<table class="form_group">
<tr>
  <td class="form_clabel">Title:</td>
  <td class="form_value">
    <input type="text" name="title" size="50" value="%(title)s" disabled>
  </td>
</tr>
<tr>
  <td class="form_label">Description:</td>
  <td class="form_value">
<textarea rows="10" cols="80" name="description" disabled>
%(description)s
</textarea>
  </td>
</table>
</td></tr>
</table>
</form>
<h1 class="%(statusClass)s">Submission %(statusName)s</h1>
%(message)s
<p>
<hr>
<a href="/">Return to Summary</a>
</body>
</html>"""%locals()
        return self.send_string(result)

    def send_open_report(self, report):
        try:
            keys = self.load_report(report)
        except IOError:
            return self.send_error(400, 'Invalid report.')

        file = keys.get('FILE')
        if not file or not posixpath.exists(file):
            return self.send_error(400, 'File does not exist: "%s"' % file)

        import startfile
        if self.server.options.debug:
            print >>sys.stderr, '%s: SERVER: opening "%s"'%(sys.argv[0],
                                                            file)

        status = startfile.open(file)
        if status:
            res = 'Opened: "%s"' % file
        else:
            res = 'Open failed: "%s"' % file

        return self.send_string(res, 'text/plain')

    def get_report_context(self, report):
        class Context:
            pass
        if report is None or report == 'None':
            data = self.load_crashes()
            # Don't allow empty reports.
            if not data:
                raise ValueError, 'No crashes detected!'
            c = Context()
            c.title = 'clang static analyzer failures'

            stderrSummary = ""
            for item in data:
                if 'stderr' in item:
                    path = posixpath.join(self.server.root, item['stderr'])
                    if os.path.exists(path):
                        lns = itertools.islice(open(path), 0, 10)
                        stderrSummary += '%s\n--\n%s' % (item.get('src', 
                                                                  '<unknown>'),
                                                         ''.join(lns))

            c.description = """\
The clang static analyzer failed on these inputs:
%s

STDERR Summary
--------------
%s
""" % ('\n'.join([item.get('src','<unknown>') for item in data]),
       stderrSummary)
            c.reportSource = None
            c.navMarkup = "Report Crashes > "
            c.files = []
            for item in data:                
                c.files.append(item.get('src',''))
                c.files.append(posixpath.join(self.server.root,
                                              item.get('file','')))
                c.files.append(posixpath.join(self.server.root,
                                              item.get('clangfile','')))
                c.files.append(posixpath.join(self.server.root,
                                              item.get('stderr','')))
                c.files.append(posixpath.join(self.server.root,
                                              item.get('info','')))
            # Just in case something failed, ignore files which don't
            # exist.
            c.files = [f for f in c.files
                       if os.path.exists(f) and os.path.isfile(f)]
        else:
            # Check that this is a valid report.            
            path = posixpath.join(self.server.root, 'report-%s.html' % report)
            if not posixpath.exists(path):
                raise ValueError, 'Invalid report ID'
            keys = self.load_report(report)
            c = Context()
            c.title = keys.get('DESC','clang error (unrecognized')
            c.description = """\
Bug reported by the clang static analyzer.

Description: %s
File: %s
Line: %s
"""%(c.title, keys.get('FILE','<unknown>'), keys.get('LINE', '<unknown>'))
            c.reportSource = 'report-%s.html' % report
            c.navMarkup = """<a href="/%s">Report %s</a> > """ % (c.reportSource,
                                                                  report)

            c.files = [path]
        return c

    def send_report(self, report, configOverrides=None):
        def getConfigOption(section, field):            
            if (configOverrides is not None and
                section in configOverrides and
                field in configOverrides[section]):
                return configOverrides[section][field]
            return self.server.config.get(section, field)

        # report is None is used for crashes
        try:
            c = self.get_report_context(report)
        except ValueError, e:
            return self.send_error(400, e.message)

        title = c.title
        description= c.description
        reportingFor = c.navMarkup
        if c.reportSource is None:
            extraIFrame = ""
        else:
            extraIFrame = """\
<iframe src="/%s" width="100%%" height="40%%"
        scrolling="auto" frameborder="1">
  <a href="/%s">View Bug Report</a>
</iframe>""" % (c.reportSource, c.reportSource)

        reporterSelections = []
        reporterOptions = []

        try:
            active = int(getConfigOption('ScanView','reporter'))
        except:
            active = 0
        for i,r in enumerate(self.server.reporters):
            selected = (i == active)
            if selected:
                selectedStr = ' selected'
            else:
                selectedStr = ''
            reporterSelections.append('<option value="%d"%s>%s</option>'%(i,selectedStr,r.getName()))
            options = '\n'.join(["""\
<tr>
  <td class="form_clabel">%s:</td>
  <td class="form_value"><input type="text" name="%s_%s" value="%s"></td>
</tr>"""%(o,r.getName(),o,getConfigOption(r.getName(),o)) for o in r.getParameterNames()])
            display = ('none','')[selected]
            reporterOptions.append("""\
<tr id="%sReporterOptions" style="display:%s">
  <td class="form_label">%s Options</td>
  <td class="form_value">
    <table class="form_inner_group">
%s
    </table>
  </td>
</tr>
"""%(r.getName(),display,r.getName(),options))
        reporterSelections = '\n'.join(reporterSelections)
        reporterOptionsDivs = '\n'.join(reporterOptions)
        reportersArray = '[%s]'%(','.join([`r.getName()` for r in self.server.reporters]))

        if c.files:
            fieldSize = min(5, len(c.files))
            attachFileOptions = '\n'.join(["""\
<option value="%d" selected>%s</option>""" % (i,v) for i,v in enumerate(c.files)])
            attachFileRow = """\
<tr>
  <td class="form_label">Attach:</td>
  <td class="form_value">
<select style="width:100%%" name="files" multiple size=%d>
%s
</select>
  </td>
</tr>
""" % (min(5, len(c.files)), attachFileOptions)
        else:
            attachFileRow = ""

        result = """<html>
<head>
  <title>File Bug</title>
  <link rel="stylesheet" type="text/css" href="/scanview.css" />
</head>
<script language="javascript" type="text/javascript">
var reporters = %(reportersArray)s;
function updateReporterOptions() {
  index = document.getElementById('reporter').selectedIndex;
  for (var i=0; i < reporters.length; ++i) {
    o = document.getElementById(reporters[i] + "ReporterOptions");
    if (i == index) {
      o.style.display = "";
    } else {
      o.style.display = "none";
    }
  }
}
</script>
<body onLoad="updateReporterOptions()">
<h3>
<a href="/">Summary</a> > 
%(reportingFor)s
File Bug</h3>
<form name="form" action="/report_submit" method="post">
<input type="hidden" name="report" value="%(report)s">

<table class="form">
<tr><td>
<table class="form_group">
<tr>
  <td class="form_clabel">Title:</td>
  <td class="form_value">
    <input type="text" name="title" size="50" value="%(title)s">
  </td>
</tr>
<tr>
  <td class="form_label">Description:</td>
  <td class="form_value">
<textarea rows="10" cols="80" name="description">
%(description)s
</textarea>
  </td>
</tr>

%(attachFileRow)s

</table>
<br>
<table class="form_group">
<tr>
  <td class="form_clabel">Method:</td>
  <td class="form_value">
    <select id="reporter" name="reporter" onChange="updateReporterOptions()">
    %(reporterSelections)s
    </select>
  </td>
</tr>
%(reporterOptionsDivs)s
</table>
<br>
</td></tr>
<tr><td class="form_submit">
  <input align="right" type="submit" name="Submit" value="Submit">
</td></tr>
</table>
</form>

%(extraIFrame)s

</body>
</html>"""%locals()

        return self.send_string(result)

    def send_head(self, fields=None):
        if (self.server.options.onlyServeLocal and
            self.client_address[0] != '127.0.0.1'):
            return self.send_error('401', 'Unauthorized host.')

        if fields is None:
            fields = {}
        self.fields = fields

        o = urlparse.urlparse(self.path)
        self.fields = parse_query(o.query, fields)
        path = posixpath.normpath(urllib.unquote(o.path))

        # Split the components and strip the root prefix.
        components = path.split('/')[1:]
        
        # Special case some top-level entries.
        if components:
            name = components[0]
            if len(components)==2:
                if name=='report':
                    return self.send_report(components[1])
                elif name=='open':
                    return self.send_open_report(components[1])
            elif len(components)==1:
                if name=='quit':
                    self.server.halt()
                    return self.send_string('Goodbye.', 'text/plain')
                elif name=='report_submit':
                    return self.send_report_submit()
                elif name=='report_crashes':
                    overrides = { 'ScanView' : {},
                                  'Radar' : {},
                                  'Email' : {} }
                    for i,r in enumerate(self.server.reporters):
                        if r.getName() == 'Radar':
                            overrides['ScanView']['reporter'] = i
                            break
                    overrides['Radar']['Component'] = 'llvm - checker'
                    overrides['Radar']['Component Version'] = 'X'
                    return self.send_report(None, overrides)
                elif name=='favicon.ico':
                    return self.send_path(posixpath.join(kResources,'bugcatcher.ico'))
        
        # Match directory entries.
        if components[-1] == '':
            components[-1] = 'index.html'

        suffix = '/'.join(components)

        # The summary may reference source files on disk using rooted
        # paths. Make sure these resolve correctly for now.
        # FIXME: This isn't a very good idea... we should probably
        # mark rooted paths somehow.        
        if os.path.exists(posixpath.join('/', suffix)):
            path = posixpath.join('/', suffix)
        else:
            path = posixpath.join(self.server.root, suffix)

        if self.server.options.debug > 1:
            print >>sys.stderr, '%s: SERVER: sending path "%s"'%(sys.argv[0],
                                                                 path)
        return self.send_path(path)

    def send_404(self):
        self.send_error(404, "File not found")
        return None

    def send_path(self, path):
        ctype = self.guess_type(path)
        if ctype.startswith('text/'):
            # Patch file instead
            return self.send_patched_file(path, ctype)
        else:
            mode = 'rb'
        try:
            f = open(path, mode)
        except IOError:
            return self.send_404()
        return self.send_file(f, ctype)

    def send_file(self, f, ctype):
        # Patch files to add links, but skip binary files.
        self.send_response(200)
        self.send_header("Content-type", ctype)
        fs = os.fstat(f.fileno())
        self.send_header("Content-Length", str(fs[6]))
        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
        self.end_headers()
        return f

    def send_string(self, s, ctype='text/html', headers=True, mtime=None):
        if headers:
            self.send_response(200)
            self.send_header("Content-type", ctype)
            self.send_header("Content-Length", str(len(s)))
            if mtime is None:
                mtime = self.dynamic_mtime
            self.send_header("Last-Modified", self.date_time_string(mtime))
            self.end_headers()
        return StringIO.StringIO(s)

    def send_patched_file(self, path, ctype):
        # Allow a very limited set of variables. This is pretty gross.
        variables = {}
        variables['report'] = ''
        m = kReportFileRE.match(path)
        if m:
            variables['report'] = m.group(2)

        try:
            f = open(path,'r')
        except IOError:
            return self.send_404()
        fs = os.fstat(f.fileno())
        data = f.read()
        for a,b in kReportReplacements:
            data = a.sub(b % variables, data)
        return self.send_string(data, ctype, mtime=fs.st_mtime)


def create_server(address, options, root):
    import Reporter

    reporters = Reporter.getReporters()

    return ScanViewServer(address, ScanViewRequestHandler,
                          root,
                          reporters,
                          options)
