#!/usr/bin/env python
#
# Copyright 2001 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Simple web server for browsing dependency graph data.

This script is inlined into the final executable and spawned by
it when needed.
"""

from __future__ import print_function

try:
    import http.server as httpserver
    import socketserver
except ImportError:
    import BaseHTTPServer as httpserver
    import SocketServer as socketserver
import argparse
import cgi
import os
import socket
import subprocess
import sys
import webbrowser
try:
    from urllib.request import unquote
except ImportError:
    from urllib2 import unquote
from collections import namedtuple

Node = namedtuple('Node', ['inputs', 'rule', 'target', 'outputs'])

# Ideally we'd allow you to navigate to a build edge or a build node,
# with appropriate views for each.  But there's no way to *name* a build
# edge so we can only display nodes.
#
# For a given node, it has at most one input edge, which has n
# different inputs.  This becomes node.inputs.  (We leave out the
# outputs of the input edge due to what follows.)  The node can have
# multiple dependent output edges.  Rather than attempting to display
# those, they are summarized by taking the union of all their outputs.
#
# This means there's no single view that shows you all inputs and outputs
# of an edge.  But I think it's less confusing than alternatives.

def match_strip(line, prefix):
    if not line.startswith(prefix):
        return (False, line)
    return (True, line[len(prefix):])

def html_escape(text):
    return cgi.escape(text, quote=True)

def parse(text):
    lines = iter(text.split('\n'))

    target = None
    rule = None
    inputs = []
    outputs = []

    try:
        target = next(lines)[:-1]  # strip trailing colon

        line = next(lines)
        (match, rule) = match_strip(line, '  input: ')
        if match:
            (match, line) = match_strip(next(lines), '    ')
            while match:
                type = None
                (match, line) = match_strip(line, '| ')
                if match:
                    type = 'implicit'
                (match, line) = match_strip(line, '|| ')
                if match:
                    type = 'order-only'
                inputs.append((line, type))
                (match, line) = match_strip(next(lines), '    ')

        match, _ = match_strip(line, '  outputs:')
        if match:
            (match, line) = match_strip(next(lines), '    ')
            while match:
                outputs.append(line)
                (match, line) = match_strip(next(lines), '    ')
    except StopIteration:
        pass

    return Node(inputs, rule, target, outputs)

def create_page(body):
    return '''<!DOCTYPE html>
<style>
body {
    font-family: sans;
    font-size: 0.8em;
    margin: 4ex;
}
h1 {
    font-weight: normal;
    font-size: 140%;
    text-align: center;
    margin: 0;
}
h2 {
    font-weight: normal;
    font-size: 120%;
}
tt {
    font-family: WebKitHack, monospace;
    white-space: nowrap;
}
.filelist {
  -webkit-columns: auto 2;
}
</style>
''' + body

def generate_html(node):
    document = ['<h1><tt>%s</tt></h1>' % html_escape(node.target)]

    if node.inputs:
        document.append('<h2>target is built using rule <tt>%s</tt> of</h2>' %
                        html_escape(node.rule))
        if len(node.inputs) > 0:
            document.append('<div class=filelist>')
            for input, type in sorted(node.inputs):
                extra = ''
                if type:
                    extra = ' (%s)' % html_escape(type)
                document.append('<tt><a href="?%s">%s</a>%s</tt><br>' %
                                (html_escape(input), html_escape(input), extra))
            document.append('</div>')

    if node.outputs:
        document.append('<h2>dependent edges build:</h2>')
        document.append('<div class=filelist>')
        for output in sorted(node.outputs):
            document.append('<tt><a href="?%s">%s</a></tt><br>' %
                            (html_escape(output), html_escape(output)))
        document.append('</div>')

    return '\n'.join(document)

def ninja_dump(target):
    cmd = [args.ninja_command, '-f', args.f, '-t', 'query', target]
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                            universal_newlines=True)
    return proc.communicate() + (proc.returncode,)

class RequestHandler(httpserver.BaseHTTPRequestHandler):
    def do_GET(self):
        assert self.path[0] == '/'
        target = unquote(self.path[1:])

        if target == '':
            self.send_response(302)
            self.send_header('Location', '?' + args.initial_target)
            self.end_headers()
            return

        if not target.startswith('?'):
            self.send_response(404)
            self.end_headers()
            return
        target = target[1:]

        ninja_output, ninja_error, exit_code = ninja_dump(target)
        if exit_code == 0:
            page_body = generate_html(parse(ninja_output.strip()))
        else:
            # Relay ninja's error message.
            page_body = '<h1><tt>%s</tt></h1>' % html_escape(ninja_error)

        self.send_response(200)
        self.end_headers()
        self.wfile.write(create_page(page_body).encode('utf-8'))

    def log_message(self, format, *args):
        pass  # Swallow console spam.

parser = argparse.ArgumentParser(prog='ninja -t browse')
parser.add_argument('--port', '-p', default=8000, type=int,
    help='Port number to use (default %(default)d)')
parser.add_argument('--hostname', '-a', default='localhost', type=str,
    help='Hostname to bind to (default %(default)s)')
parser.add_argument('--no-browser', action='store_true',
    help='Do not open a webbrowser on startup.')

parser.add_argument('--ninja-command', default='ninja',
    help='Path to ninja binary (default %(default)s)')
parser.add_argument('-f', default='build.ninja',
    help='Path to build.ninja file (default %(default)s)')
parser.add_argument('initial_target', default='all', nargs='?',
    help='Initial target to show (default %(default)s)')

class HTTPServer(socketserver.ThreadingMixIn, httpserver.HTTPServer):
    # terminate server immediately when Python exits.
    daemon_threads = True

args = parser.parse_args()
port = args.port
hostname = args.hostname
httpd = HTTPServer((hostname,port), RequestHandler)
try:
    if hostname == "":
        hostname = socket.gethostname()
    print('Web server running on %s:%d, ctl-C to abort...' % (hostname,port) )
    print('Web server pid %d' % os.getpid(), file=sys.stderr )
    if not args.no_browser:
        webbrowser.open_new('http://%s:%s' % (hostname, port) )
    httpd.serve_forever()
except KeyboardInterrupt:
    print()
    pass  # Swallow console spam.


