# Lint as: python3
# pylint: disable=g-direct-third-party-import
# Copyright 2022 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.
"""A tool for building the documentation for a Bazel release."""
import os
import sys
import tarfile
import tempfile
import zipfile

from absl import app
from absl import flags

from scripts.docs import rewriter

FLAGS = flags.FLAGS

flags.DEFINE_string("version", None, "Name of the Bazel release.")
flags.DEFINE_string(
    "narrative_docs_path",
    None,
    "Path of the archive (zip or tar) that contains the narrative documentation.",
)
flags.DEFINE_string(
    "reference_docs_path",
    None,
    "Path of the archive (zip or tar) that contains the reference documentation.",
)
flags.DEFINE_string(
    "output_path", None,
    "Location where the zip'ed documentation should be written to.")

flags.mark_flag_as_required("version")
flags.mark_flag_as_required("narrative_docs_path")
flags.mark_flag_as_required("reference_docs_path")
flags.mark_flag_as_required("output_path")

_ARCHIVE_FUNCTIONS = {".tar": tarfile.open, ".zip": zipfile.ZipFile}


def create_docs_tree(
    version, narrative_docs_path, reference_docs_path
):
  """Creates a directory tree containing the docs for the Bazel version.

  Args:
    version: Version of this Bazel release.
    narrative_docs_path: Absolute path of an archive that contains the narrative
      documentation (can be .zip or .tar).
    reference_docs_path: Absolute path of an archive that contains the reference
      documentation (can be .zip or .tar).

  Returns:
    The absolute paths of the root of the directory tree.
  """
  root_dir = tempfile.mkdtemp()

  versions_dir = os.path.join(root_dir, "versions")
  os.makedirs(versions_dir)

  release_dir = os.path.join(versions_dir, version)
  os.makedirs(release_dir)

  try_extract(narrative_docs_path, release_dir)
  try_extract(reference_docs_path, release_dir)

  return root_dir, release_dir


def try_extract(archive_path, output_dir):
  """Tries to extract the given archive into the given directory.

  This function will raise an error if the archive type is not supported.

  Args:
    archive_path: Absolute path of an archive that should be extracted. Can be
      .tar or .zip.
    output_dir: Absolute path of the directory into which the archive should be
      extracted

  Raises:
    ValueError: If the archive has an unsupported file type.
  """
  _, ext = os.path.splitext(archive_path)
  open_func = _ARCHIVE_FUNCTIONS.get(ext)
  if not open_func:
    raise ValueError("File {}: Invalid file extension '{}'. Allowed: {}".format(
        archive_path, ext, _ARCHIVE_FUNCTIONS.keys.join(", ")))

  with open_func(archive_path, "r") as archive:
    archive.extractall(output_dir)


def build_archive(version, root_dir, output_path, release_dir):
  """Builds a documentation archive for the given Bazel release.

  This function reads all documentation files from the tree rooted in root_dir,
  fixes all links so that they point at versioned files, then builds a zip
  archive of all files.

  Args:
    version: Version of the Bazel release whose documentation is being built.
    root_dir: Absolute path of the directory that contains the documentation
      tree.
    output_path: Absolute path where the archive should be written to.
    release_dir: Absolute path of the root directory for this version.
  """
  with zipfile.ZipFile(output_path, "w") as archive:
    for root, _, files in os.walk(root_dir):
      for f in files:
        src = os.path.join(root, f)
        dest = src[len(root_dir) + 1:]
        rel_path = os.path.relpath(src, release_dir)

        if rewriter.can_rewrite(src):
          archive.writestr(dest, get_versioned_content(src, rel_path, version))
        else:
          archive.write(src, dest)


def get_versioned_content(path, rel_path, version):
  """Rewrites links in the given file to point at versioned docs.

  Args:
    path: Absolute path of the file that should be rewritten.
    rel_path: Relative path of the file that should be rewritten.
    version: Version of the Bazel release whose documentation is being built.

  Returns:
    The content of the given file, with rewritten links.
  """
  with open(path, "rt", encoding="utf-8") as f:
    content = f.read()

  return rewriter.rewrite_links(path, content, rel_path, version)


def main(unused_argv):
  version = FLAGS.version
  output_path = FLAGS.output_path
  root_dir, release_dir = create_docs_tree(
      version=version,
      narrative_docs_path=FLAGS.narrative_docs_path,
      reference_docs_path=FLAGS.reference_docs_path,
  )

  build_archive(
      version=version,
      root_dir=root_dir,
      output_path=output_path,
      release_dir=release_dir,
  )


if __name__ == "__main__":
  FLAGS(sys.argv)
  app.run(main)
