try:
    from http.server import HTTPServer, SimpleHTTPRequestHandler
except ImportError:
    from BaseHTTPServer import HTTPServer
    from SimpleHTTPServer import SimpleHTTPRequestHandler
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.

# Disabled for the time being until we decide exactly when this should
# be enabled. Also the radar reporter needs to be fixed to report
# multiple files.

#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

kShare = posixpath.join(posixpath.dirname(__file__), '../share/scan-view')
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 as e:
            self.status = e.value
        except Exception as 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(HTTPServer):
    def __init__(self, address, handler, root, reporters, options):
        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.getParameters():
              if p.saveConfigValue():
                self.config.set(r.getName(), p.getName(), '')

        # 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 as e:
                print 'OSError',e.errno

    def finish_request(self, request, client_address):
        if self.options.autoReload:
            import ScanView
            self.RequestHandlerClass = reload(ScanView).ScanViewRequestHandler
        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
        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(SimpleHTTPRequestHandler):
    server_version = "ScanViewServer/" + __version__
    dynamic_mtime = time.time()

    def do_HEAD(self):
        try:
            SimpleHTTPRequestHandler.do_HEAD(self)
        except Exception as e:
            self.handle_exception(e)
            
    def do_GET(self):
        try:
            SimpleHTTPRequestHandler.do_GET(self)
        except Exception as 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 as 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])
        
        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.getParameters():
            name = '%s_%s'%(reporter.getName(),o.getName())
            if name not in self.fields:
                return (False, 
                        'Missing field "%s" for %s report method.'%(name,
                                                                    reporter.getName()))
            parameters[o.getName()] = self.get_scalar_field(name)

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

        # 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):
        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(object):
            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 as 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([ o.getHTML(r,title,getConfigOption) for o in r.getParameters()])
            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([repr(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(kShare,'bugcatcher.ico'))
        
        # Match directory entries.
        if components[-1] == '':
            components[-1] = 'index.html'

        relpath = '/'.join(components)
        path = posixpath.join(self.server.root, relpath)

        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):
        # If the requested path is outside the root directory, do not open it
        rel = os.path.abspath(path)
        if not rel.startswith(os.path.abspath(self.server.root)):
          return self.send_404()
        
        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)
