# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Simple Markdown browser for a Git checkout."""
from __future__ import print_function

import SimpleHTTPServer
import SocketServer
import argparse
import codecs
import os
import re
import socket
import sys


THIS_DIR = os.path.abspath(os.path.dirname(__file__))
SRC_DIR = os.path.dirname(os.path.dirname(THIS_DIR))
sys.path.append(os.path.join(SRC_DIR, 'third_party', 'Python-Markdown'))
import markdown


def main(argv):
  parser = argparse.ArgumentParser(prog='md_browser')
  parser.add_argument('-p', '--port', type=int, default=8080,
                      help='port to run on (default = %(default)s)')
  args = parser.parse_args(argv)

  try:
    s = Server(args.port, SRC_DIR)
    print("Listening on http://localhost:%s/" % args.port)
    print(" Try loading http://localhost:%s/docs/README.md" % args.port)
    s.serve_forever()
    s.shutdown()
    return 0
  except KeyboardInterrupt:
    return 130


def _gitiles_slugify(value, _separator):
  """Convert a string (representing a section title) to URL anchor name.

  This function is passed to "toc" extension as an extension option, so we
  can emulate the way how Gitiles converts header titles to URL anchors.

  Gitiles' official documentation about the conversion is at:

  https://gerrit.googlesource.com/gitiles/+/master/Documentation/markdown.md#Named-anchors

  Args:
    value: The name of a section that is to be converted.
    _separator: Unused. This is actually a configurable string that is used
        as a replacement character for spaces in the title, typically set to
        '-'. Since we emulate Gitiles' way of slugification here, it makes
        little sense to have the separator charactor configurable.
  """

  # TODO(yutak): Implement accent removal. This does not seem easy without
  # some library. For now we just make accented characters turn into
  # underscores, just like other non-ASCII characters.

  value = value.encode('ascii', 'replace')  # Non-ASCII turns into '?'.
  value = re.sub(r'[^- a-zA-Z0-9]', '_', value)  # Non-alphanumerics to '_'.
  value = value.replace(u' ', u'-')
  value = re.sub(r'([-_])[-_]+', r'\1', value)  # Fold hyphens and underscores.
  return value


class Server(SocketServer.TCPServer):
  def __init__(self, port, top_level):
    SocketServer.TCPServer.__init__(self, ('0.0.0.0', port), Handler)
    self.port = port
    self.top_level = top_level

  def server_bind(self):
    self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    self.socket.bind(self.server_address)


class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
  def do_GET(self):
    path = self.path

    # strip off the repo and branch info, if present, for compatibility
    # with gitiles.
    if path.startswith('/chromium/src/+/master'):
      path = path[len('/chromium/src/+/master'):]

    full_path = os.path.abspath(os.path.join(self.server.top_level, path[1:]))

    if not full_path.startswith(SRC_DIR):
      self._DoUnknown()
    elif path == '/doc.css':
      self._WriteTemplate('doc.css')
    elif not os.path.exists(full_path):
      self._DoNotFound()
    elif path.lower().endswith('.md'):
      self._DoMD(path)
    elif os.path.exists(full_path + '/README.md'):
      self._DoMD(path + '/README.md')
    else:
      self._DoUnknown()

  def _DoMD(self, path):
    extensions = [
        'markdown.extensions.def_list',
        'markdown.extensions.fenced_code',
        'markdown.extensions.tables',
        'markdown.extensions.toc',
        'gitiles_ext_blocks',
    ]
    extension_configs = {
        'markdown.extensions.toc': {
            'slugify': _gitiles_slugify
        },
    }

    contents = self._Read(path[1:])
    md_fragment = markdown.markdown(contents,
                                    extensions=extensions,
                                    extension_configs=extension_configs,
                                    output_format='html4').encode('utf-8')
    try:
      self._WriteTemplate('header.html')
      self.wfile.write(md_fragment)
      self._WriteTemplate('footer.html')
    except:
      raise

  def _DoNotFound(self):
    self.wfile.write('<html><body>%s not found</body></html>' % self.path)

  def _DoUnknown(self):
    self.wfile.write('<html><body>I do not know how to serve %s.</body>'
                       '</html>' % self.path)

  def _Read(self, relpath):
    assert not relpath.startswith(os.sep)
    path = os.path.join(self.server.top_level, relpath)
    with codecs.open(path, encoding='utf-8') as fp:
      return fp.read()

  def _WriteTemplate(self, template):
    contents = self._Read(os.path.join('tools', 'md_browser', template))
    self.wfile.write(contents.encode('utf-8'))


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
