# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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 script to convert cassandra.yaml into ReStructuredText for
the online documentation.

Usage:

    convert_yaml_to_rest.py conf/cassandra.yaml docs/source/conf.rst
"""

import sys
import re

# Detects options, whether commented or uncommented.
# Group 1 will be non-empty if the option is commented out.
# Group 2 will contain the option name.
# Group 3 will contain the default value, if one exists.
option_re = re.compile(r"^(# ?)?([a-z0-9_]+): ?([^/].*)")

# Detects normal comment lines.
commented_re = re.compile(r"^# ?(.*)")

# A set of option names that have complex values (i.e. lists or dicts).
# This list is hardcoded because there did not seem to be another
# good way to reliably detect this case, especially considering
# that these can be commented out (making it useless to use a yaml parser).
COMPLEX_OPTIONS = (
    'seed_provider',
    'request_scheduler_options',
    'data_file_directories',
    'commitlog_compression',
    'hints_compression',
    'server_encryption_options',
    'client_encryption_options',
    'transparent_data_encryption_options',
    'hinted_handoff_disabled_datacenters'
)


def convert(yaml_file, dest_file):
    with open(yaml_file, 'r') as f:
        # Trim off the boilerplate header
        lines = f.readlines()[7:]

    with open(dest_file, 'w') as outfile:
        outfile.write(".. _cassandra-yaml:\n")
        outfile.write("\n")
        outfile.write("Cassandra Configuration File\n")
        outfile.write("============================\n")

        # since comments preceed an option, this holds all of the comment
        # lines we've seen since the last option
        comments_since_last_option = []
        line_iter = iter(lines)
        while True:
            try:
                line = next(line_iter)
            except StopIteration:
                break

            match = option_re.match(line)
            if match:
                option_name = match.group(2)
                is_commented = bool(match.group(1))

                is_complex = option_name in COMPLEX_OPTIONS
                complex_option = read_complex_option(line_iter) if is_complex else None

                write_section_header(option_name, outfile)
                write_comments(comments_since_last_option, is_commented, outfile)
                if is_complex:
                    write_complex_option(complex_option, outfile)
                else:
                    maybe_write_default_value(match, outfile)
                comments_since_last_option = []
            else:
                comment_match = commented_re.match(line)
                if comment_match:
                    comments_since_last_option.append(comment_match.group(1))
                elif line == "\n":
                    comments_since_last_option.append('')


def write_section_header(option_name, outfile):
    outfile.write("\n")
    outfile.write("``%s``\n" % (option_name,))
    outfile.write("-" * (len(option_name) + 4) + "\n")


def write_comments(comment_lines, is_commented, outfile):
    if is_commented:
        outfile.write("*This option is commented out by default.*\n")

    for comment in comment_lines:
        if "SAFETY THRESHOLDS" not in comment_lines:
            outfile.write(comment + "\n")


def maybe_write_default_value(option_match, outfile):
    default_value = option_match.group(3)
    if default_value and default_value != "\n":
        outfile.write("\n*Default Value:* %s\n" % (default_value,))


def read_complex_option(line_iter):
    option_lines = []
    try:
        while True:
            line = next(line_iter)
            if line == '\n':
                return option_lines
            else:
                option_lines.append(line)
    except StopIteration:
        return option_lines


def write_complex_option(lines, outfile):
    outfile.write("\n*Default Value (complex option)*::\n\n")
    for line in lines:
        outfile.write((" " * 4) + line)


if __name__ == '__main__':
    if len(sys.argv) != 3:
        print >> sys.stderr, "Usage: %s <yaml source file> <rst dest file>" % (sys.argv[0],)
        sys.exit(1)

    yaml_file = sys.argv[1]
    dest_file = sys.argv[2]
    convert(yaml_file, dest_file)
