# Copyright 2016 The Bazel Authors. 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.

"""Documentation generator for Skylark"""

from __future__ import print_function
# internal imports
import jinja2
import mistune
import os
import posixpath
import re
import shutil
import sys
import tempfile
import zipfile

from optparse import OptionParser

from bazel_tools.tools.python.runfiles import runfiles as runfiles_lib
from skydoc import common
from skydoc import load_extractor
from skydoc import macro_extractor
from skydoc import rule
from skydoc import rule_extractor

DEFAULT_OUTPUT_DIR = '.'
DEFAULT_OUTPUT_FILE = 'skydoc.zip'

WORKSPACE_DIR = 'io_bazel_skydoc'
TEMPLATE_PATH = 'skydoc/templates'
CSS_PATH = 'skydoc/sass'

CSS_FILE = 'main.css'

def _create_jinja_environment(runfiles, site_root, link_ext):
  def _Load(path):
    loc = runfiles.Rlocation(posixpath.join(WORKSPACE_DIR, TEMPLATE_PATH, path))
    if loc:
      with open(loc, "rb") as f:
        return f.read().decode("utf-8")
    return None

  env = jinja2.Environment(
      loader=jinja2.FunctionLoader(_Load),
      keep_trailing_newline=True,
      line_statement_prefix='%')
  env.filters['markdown'] = lambda text: jinja2.Markup(mistune.markdown(text))
  env.filters['doc_link'] = (
      lambda fname: site_root + '/' + fname + '.' + link_ext)
  env.filters['link'] = lambda fname: site_root + '/' + fname
  return env


# TODO(dzc): Remove this workaround once we switch to a self-contained Python
# binary format such as PEX.
def _runfile_path(runfiles, path):
  return runfiles.Rlocation(posixpath.join(WORKSPACE_DIR, path))

def merge_languages(macro_language, rule_language):
  for rule in rule_language.rule:
    new_rule = macro_language.rule.add()
    new_rule.CopyFrom(rule)
  return macro_language

class WriterOptions(object):
  def __init__(self, output_dir, output_file, output_zip, overview,
               overview_filename, link_ext, site_root):
    self.output_dir = output_dir
    self.output_file = output_file
    self.output_zip = output_zip
    self.overview = overview
    self.overview_filename = overview_filename
    self.link_ext = link_ext

    self.site_root = site_root
    if len(self.site_root) > 0 and self.site_root.endswith('/'):
        self.site_root = self.site_root[:-1]

class MarkdownWriter(object):
  """Writer for generating documentation in Markdown."""

  def __init__(self, writer_options, runfiles):
    self.__options = writer_options
    self.__env = _create_jinja_environment(runfiles,
                                           self.__options.site_root,
                                           self.__options.link_ext)

  def write(self, rulesets):
    """Write the documentation for the rules contained in rulesets."""
    try:
      temp_dir = tempfile.mkdtemp()
      output_files = []
      for ruleset in rulesets:
        if not ruleset.empty():
          output_files.append(self._write_ruleset(temp_dir, ruleset))
      if self.__options.overview:
        output_files.append(self._write_overview(temp_dir, rulesets))

      if self.__options.output_zip:
        # We are generating a zip archive containing all the documentation.
        # Write each documentation file generated in the temp directory to the
        # zip file.
        with zipfile.ZipFile(self.__options.output_file, 'w') as zf:
          for output_file, output_path in output_files:
            zf.write(output_file, output_path)
      else:
        # We are generating documentation in the output_dir directory. Copy each
        # documentation file to output_dir.
        for output_file, output_path in output_files:
          dest_file = os.path.join(self.__options.output_dir, output_path)
          dest_dir = os.path.dirname(dest_file)
          if not os.path.exists(dest_dir):
            os.makedirs(dest_dir)
          shutil.copyfile(output_file, dest_file)

    finally:
      # Delete temporary directory.
      shutil.rmtree(temp_dir)

  def _write_ruleset(self, output_dir, ruleset):
    # Load template and render Markdown.
    template = self.__env.get_template('markdown.jinja')
    out = template.render(ruleset=ruleset)

    # Write output to file. Output files are created in a directory structure
    # that matches that of the input file.
    output_path = ruleset.output_file + '.md'
    output_file = "%s/%s" % (output_dir, output_path)
    file_dirname = os.path.dirname(output_file)
    if not os.path.exists(file_dirname):
      os.makedirs(file_dirname)
    with open(output_file, "w") as f:
      f.write(out)
    return (output_file, output_path)

  def _write_overview(self, output_dir, rulesets):
    template = self.__env.get_template('markdown_overview.jinja')
    out = template.render(rulesets=rulesets)

    output_file = "%s/%s.md" % (output_dir, self.__options.overview_filename)
    with open(output_file, "w") as f:
      f.write(out)
    return (output_file, "%s.md" % self.__options.overview_filename)

class HtmlWriter(object):
  """Writer for generating documentation in HTML."""

  def __init__(self, options, runfiles):
    self.__runfiles = runfiles
    self.__options = options
    self.__env = _create_jinja_environment(runfiles,
                                           self.__options.site_root,
                                           self.__options.link_ext)

  def write(self, rulesets):
    # Generate navigation used for all rules.
    nav_template = self.__env.get_template('nav.jinja')
    nav = nav_template.render(
        rulesets=rulesets,
        overview=self.__options.overview,
        overview_filename=self.__options.overview_filename)

    try:
      temp_dir = tempfile.mkdtemp()
      output_files = []
      for ruleset in rulesets:
        if not ruleset.empty():
          output_files.append(self._write_ruleset(temp_dir, ruleset, nav))
      if self.__options.overview:
        output_files.append(self._write_overview(temp_dir, rulesets, nav))

      if self.__options.output_zip:
        with zipfile.ZipFile(self.__options.output_file, 'w') as zf:
          for output_file, output_path in output_files:
            zf.write(output_file, output_path)
          zf.write(_runfile_path(self.__runfiles,
                                 posixpath.join(CSS_PATH, CSS_FILE)),
                   CSS_FILE)
      else:
        for output_file, output_path in output_files:
          dest_file = os.path.join(self.__options.output_dir, output_path)
          dest_dir = os.path.dirname(dest_file)
          if not os.path.exists(dest_dir):
            os.makedirs(dest_dir)
          shutil.copyfile(output_file, dest_file)

        # Copy CSS file.
        shutil.copyfile(_runfile_path(self.__runfiles,
                                      posixpath.join(CSS_PATH, CSS_FILE)),
                        os.path.join(self.__options.output_dir, CSS_FILE))
    finally:
      # Delete temporary directory.
      shutil.rmtree(temp_dir)

  def _write_ruleset(self, output_dir, ruleset, nav):
    # Load template and render markdown.
    template = self.__env.get_template('html.jinja')
    out = template.render(title=ruleset.title, ruleset=ruleset, nav=nav)

    # Write output to file. Output files are created in a directory structure
    # that matches that of the input file.
    output_path = ruleset.output_file + '.html'
    output_file = "%s/%s" % (output_dir, output_path)
    file_dirname = os.path.dirname(output_file)
    if not os.path.exists(file_dirname):
      os.makedirs(file_dirname)
    with open(output_file, "w") as f:
      f.write(out)
    return (output_file, output_path)

  def _write_overview(self, output_dir, rulesets, nav):
    template = self.__env.get_template('html_overview.jinja')
    out = template.render(title='Overview', rulesets=rulesets, nav=nav)

    output_file = "%s/%s.html" % (output_dir, self.__options.overview_filename)
    with open(output_file, "w") as f:
      f.write(out)
    return (output_file, "%s.html" % self.__options.overview_filename)

def main(argv):
  parser = OptionParser()
  parser.add_option('--output_dir', default='',
      help='The directory to write the output generated documentation to if --zip=false')
  parser.add_option('--output_file', default='',
      help='The output zip archive file to write if --zip=true.')
  parser.add_option('--format', default='markdown',
      help='The output format. Possible values are markdown and html')
  parser.add_option('--zip', action='store_true', default=True,
      help='Whether to generate a ZIP arhive containing the output files. If '
           '--zip is true, then skydoc will generate a zip file, skydoc.zip by '
           'default or as specified by --output_file. If --zip is false, then '
           'skydoc will generate documentation, either in Markdown or HTML as '
           'specifed by --format, in the current directory or --output_dir if set.')
  parser.add_option('--strip_prefix', default='',
      help='The directory prefix to strip from all generated docs, which are '
           'generated in subdirectories that match the package structure of the '
           'input .bzl files. The prefix to strip must be common to all .bzl files; '
           'otherwise, skydoc will raise an error.')
  parser.add_option('--overview', action='store_true',
      help='Whether to generate an overview page')
  parser.add_option('--overview_filename', default='index',
      help='The file name to use for the overview page.')
  parser.add_option('--link_ext', default='html',
      help='The file extension used for links in the generated documentation')
  parser.add_option('--site_root', default='',
      help='The site root to be prepended to all URLs in the generated documentation')
  (options, args) = parser.parse_args(argv)

  if options.output_dir and options.output_file:
    sys.stderr.write('Only one of --output_dir or --output_file can be set.')
    sys.exit(1)

  if not options.output_dir:
    options.output_dir = DEFAULT_OUTPUT_DIR
  if not options.output_file:
    options.output_file = DEFAULT_OUTPUT_FILE

  bzl_files = args[1:]

  try:
    strip_prefix = common.validate_strip_prefix(options.strip_prefix, bzl_files)
  except common.InputError as err:
    print(err.message)
    sys.exit(1)

  runfiles = runfiles_lib.Create()
  if not runfiles:
    # TODO(laszlocsomor): fix https://github.com/bazelbuild/bazel/issues/6212
    # and remove this if-block once Bazel is released with that bugfix.
    if (not os.environ.get("RUNFILES_DIR") and
        not os.environ.get("RUNFILES_MANIFEST_FILE")):
      argv0 = sys.argv[0]
      pos = argv0.rfind('%s%s%s' % (os.sep, WORKSPACE_DIR, os.sep))
      if pos > -1:
        dirpath = argv0[0:pos]
        if not os.path.isdir(dirpath):
          print("ERROR: Cannot access runfiles directory (%s)" % dirpath)
          sys.exit(1)
        runfiles = runfiles_lib.CreateDirectoryBased(dirpath)

  if not runfiles:
    print("ERROR: Cannot load runfiles")
    sys.exit(1)

  rulesets = []
  load_sym_extractor = load_extractor.LoadExtractor()
  for bzl_file in bzl_files:
    load_symbols = []
    try:
      load_symbols = load_sym_extractor.extract(bzl_file)
    except load_extractor.LoadExtractorError as e:
      print("ERROR: Error extracting loaded symbols from %s: %s" %
            (bzl_file, str(e)))
      sys.exit(2)

    # TODO(dzc): Make MacroDocExtractor and RuleDocExtractor stateless.
    macro_doc_extractor = macro_extractor.MacroDocExtractor()
    rule_doc_extractor = rule_extractor.RuleDocExtractor()
    macro_doc_extractor.parse_bzl(bzl_file)
    rule_doc_extractor.parse_bzl(bzl_file, load_symbols)
    merged_language = merge_languages(macro_doc_extractor.proto(),
                                      rule_doc_extractor.proto())
    rulesets.append(
        rule.RuleSet(bzl_file, merged_language, macro_doc_extractor.title,
                     macro_doc_extractor.description, strip_prefix,
                     options.format))
  writer_options = WriterOptions(
      options.output_dir, options.output_file, options.zip, options.overview,
      options.overview_filename, options.link_ext, options.site_root)
  if options.format == "markdown":
    markdown_writer = MarkdownWriter(writer_options, runfiles)
    markdown_writer.write(rulesets)
  elif options.format == "html":
    html_writer = HtmlWriter(writer_options, runfiles)
    html_writer.write(rulesets)
  else:
    sys.stderr.write(
        'Invalid output format: %s. Possible values are markdown and html'
        % options.format)

if __name__ == '__main__':
  main(sys.argv)
