#!/usr/bin/env fuchsia-vendored-python
# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

#### CATEGORY=Documentation
### Helper tool to batch move docs from one location to another

## Usage: fx move-docs [--dry-run] INPUT_FILE
##        cat INPUT_FILE | fx move-docs [--dry-run]
##        echo "docs/orig/file.md doc/new_location/_toc.yaml" | fx move-docs [--dry-run]
##
## INPUT_FILE is a file with two columns, where the first column
## is the original location of the doc to be moved, and the second
## line is the destination _toc.yaml file.
##
## This tool will locate the original and destination _toc.yaml files,
## update them and update any reference to the original file.
##
## It will also create a proper entry in the _redirects.yaml file.
##
import argparse
import os
import sys
import shutil
import re
import fnmatch
import pathlib

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

         # Please, read https://fuchsia.dev/fuchsia-src/contribute/docs/documentation-navigation-toc
         # before making changes to this file, and add a member of the fuchsia.dev
         # team as reviewer.
         toc: """

def process_file(orig, dest_yaml):
    print("***** Processing %s:" % orig)

    orig_yaml=os.path.join(os.path.dirname(orig), "_toc.yaml")
    dest=os.path.join(os.path.dirname(dest_yaml), os.path.basename(orig))

    if not os.path.basename(dest_yaml) == '_toc.yaml':
        print("Destination TOC has to be named _toc.yaml: %s" % dest_yaml)
        return False
    if not os.path.exists(orig):
        print("Original file does not exist: %s" % orig)
        return False
    if not os.path.exists(orig_yaml):
        print("_toc.yaml for the original file does not exist: %s" % orig_yaml)
        return False
    if os.path.exists(dest):
        print("Destination file exists: %s" % dest)
        return False
    if not os.path.exists(dest_yaml):
        if dry_run:
            print("...dryrun...   Creating destination _toc.yaml: %s" % dest_yaml)
        else:
            pathlib.Path(os.path.dirname(dest_yaml)).mkdir(parents=True, exist_ok=True)
            with open(dest_yaml, "w") as f:
                f.write(TOC_H)

    # We can't use yaml library because it throws away comments and styles. Since
    # we just want to do basic manipulation on relatively well-behaved yaml
    # files, we will hack it.
    with open(orig_yaml) as f:
        orig_lines = f.readlines()

    new_lines = []
    entry=[]
    target_entry=None
    started_toc=False
    is_target=False
    for line in orig_lines:
        if not started_toc:
            new_lines.append(line)
            if re.search(r'^\s*toc:\s*$', line):
                started_toc=True
            continue
        if re.search(r'^\s*- ', line):
            if len(entry):
                if is_target:
                    target_entry = entry
                else:
                    new_lines.extend(entry)
            entry = []
            is_target = False
        elif re.search(r'\s*[\s-]\s*path:\s*"?' + re.escape("/" + orig), line):
            is_target = True
        entry.append(line)

    if len(entry):
        if is_target:
            target_entry = entry
        else:
            new_lines.extend(entry)

    if not target_entry:
        print("ERROR: could not find the original TOC entry in %s" % orig_yaml)
        return False

    if dry_run:
        print("...dryrun...   Removing entry from %s:" % orig_yaml)
        print(''.join(target_entry))
    else:
      with open(orig_yaml, 'w') as f:
        print(''.join(new_lines), file=f)

    # Add the entry to the destination _toc.yaml file
    new_target_entry = [re.sub(re.escape(orig), dest, line) for line in target_entry]
    if dry_run:
        print("...dryrun...   Adding entry to the end of %s:" % dest_yaml)
        print(''.join(new_target_entry))
    else:
      with open(dest_yaml, 'a') as f:
        print('\n', file=f)
        print(''.join(new_target_entry), file=f)

    # Move the original file to the destination
    if dry_run:
        print("...dryrun...   Moving file %s to %s" % (orig, dest))
    else:
        shutil.move(orig, dest)

    # Replace usage of the original file in all *.md docs
    docs_dir=os.path.join(os.environ['FUCHSIA_DIR'], 'docs')
    find_replace(docs_dir, orig, dest, '*.md')

    # Add an entry to _redirects.yaml
    redirect=['- from: /%s' % orig, '  to: /%s' % dest]
    redirect_file=os.path.join(docs_dir, '_redirects.yaml')
    if dry_run:
        print('...dryrun...   Adding entry to docs/_redirects.yaml:')
        print('\n'.join(redirect))
        print('\n')
    else:
        with open(redirect_file, 'a' if os.path.exists(redirect_file) else 'w') as f:
          print('\n', file=f)
          print('\n'.join(redirect), file=f)

    return True

def find_replace(directory, find, replace, filePattern):
    for path, dirs, files in os.walk(os.path.abspath(directory)):
        for filename in fnmatch.filter(files, filePattern):
            filepath = os.path.join(path, filename)
            with open(filepath) as f:
                s = f.read()
            new_s = s.replace(find, replace)
            if s != new_s:
                if dry_run:
                    print("###   Changing references in %s" %
                            os.path.relpath(filepath, directory))
                else:
                    with open(filepath, "w") as f:
                        f.write(new_s)

def is_file_toc(filename, toc):
    if filename[0] != '/':
        filename='/' + filename
    return toc['path'] == filename

def main():
    parser = argparse.ArgumentParser(
        description=u"Move docs in batch")

    parser.add_argument(
        "input_file",
        nargs=u"?",
        default=u"",
        help="Filename with one entry per line, each entry being space-separated strings for the original file and the destination _toc.yaml")

    parser.add_argument(
        "--dry-run",
        action="store_const",
        default=False,
        const=True,
        help="Does not modify any file",
    )

    args = parser.parse_args()

    global dry_run
    dry_run = args.dry_run

    if args.input_file:
      input_file = open(args.input_file)
    else:
      input_file = sys.stdin


    for line in input_file.readlines():
        orig, dest_yaml = line.split()
        orig = orig[1:] if orig.startswith('/docs') else orig
        dest_yaml = dest_yaml[1:] if dest_yaml.startswith('/docs') else dest_yaml
        process_file(orig, dest_yaml)

    if input_file is not sys.stdin:
        input_file.close()

    sys.exit(0)


if __name__ == u"__main__":
    sys.exit(main())
