#!/usr/bin/python3
#
# Copyright 2016-2023 The Khronos Group Inc.
#
# SPDX-License-Identifier: Apache-2.0

# Retroactively insert markup in show both 1.1 core features and KHR
# extensions they were promoted from.

# Usage: promote.py [-overwrite] [-out dir] [-suffix str] files
#   -overwrite updates in place (can be risky, make sure there are backups)
#   -out specifies directory to create output file in, default 'out'
#   -suffix specifies suffix to add to output files, default ''
#   files are asciidoc source files from the Vulkan spec to reflow.

# For error and file-loading interfaces only
import argparse, copy, os, pdb, re, string, sys
from reflib import *
from promoted import *

global anchor
anchor = 0

def anchorname(anchor):
    return 'promoted-' + str(anchor)

def printanchor(fp):
    # Anchor index for navigation
    global anchor

    print('[[' + anchorname(anchor) + ']]', file=fp)
    print('This anchor:', anchorname(anchor), file=fp)
    print('<<' + anchorname(anchor+1) + ', OINK>>', file=fp)
    anchor = anchor + 1

# promote a core interface and include the extension it was promoted from
#   line - matching line with 1.1 interface
#   type - 'protos', 'structs', 'flags', 'enums'
#   name - interface name
#   extension - name of extension interface was promoted from
#   fp - output filename
def promote(line, type, name, extension, fp):
    if type == 'protos':
        # printanchor(fp)
        print('ifdef::VK_VERSION_1_1[]', file=fp)
        print(line, file=fp, end='')
        print('endif::VK_VERSION_1_1[]', file=fp)
        print('', file=fp)
        print('ifdef::VK_VERSION_1_1+' + extension +
              '[or the equivalent command]', file=fp)
        print('', file=fp)
        print('ifdef::' + extension + '[]', file=fp)
        print('include::../api/' + type + '/' + name + 'KHR.adoc[]', file=fp)
        print('endif::' + extension + '[]', file=fp)
        del promoted[name]
    elif type == 'structs' or type == 'enums' or type == 'flags' or type == 'handles':
        # printanchor(fp)
        print(line, file=fp, end='')
        print('', file=fp)
        print('ifdef::' + extension + '[]', file=fp)
        print('or the equivalent', file=fp)
        print('', file=fp)
        print('include::../api/' + type + '/' + name + 'KHR.adoc[]', file=fp)
        print('endif::' + extension + '[]', file=fp)
        del promoted[name]
    else:
        logWarn('Unrecognized promoted type', type, 'for interface', name)
        print(line, file=fp, end='')


def promoteFile(filename, args):
    logDiag('promote: filename', filename)

    lines = loadFile(filename)
    if (lines == None):
        return

    # Output file handle and promote object for this file. There are no race
    # conditions on overwriting the input, but it is not recommended unless
    # you have backing store such as git.

    if args.overwrite:
        outFilename = filename
    else:
        outFilename = args.outDir + '/' + os.path.basename(filename) + args.suffix

    try:
        fp = open(outFilename, 'w', encoding='utf8')
        True
    except:
        logWarn('Cannot open output file', filename, ':', sys.exc_info()[0])
        return None

    lineno = 0
    for line in lines:
        lineno = lineno + 1

        matches = includePat.search(line)
        if matches != None:
            type = matches.group('type')
            name = matches.group('name')
            if name in promoted:
                extension = promoted[name]['extension']
                if extension:
                    # Promote core interface
                    promote(line, type, name, promoted[name]['extension'], fp)
                    continue
        # Fallthrough
        print(line, file=fp, end='')

    fp.close()

def promoteAllAdocFiles(folder_to_promote, args):
    for root, subdirs, files in os.walk(folder_to_promote):
        for file in files:
            if file.endswith(".adoc"):
                file_path = os.path.join(root, file)
                promoteFile(file_path, args)
        for subdir in subdirs:
            sub_folder = os.path.join(root, subdir)
            print('Sub-folder = %s' % sub_folder)
            if not (subdir.lower() == "scripts") and not (subdir.lower() == "style"):
                print('   Parsing = %s' % sub_folder)
                promoteAllAdocFiles(sub_folder, args)
            else:
                print('   Skipping = %s' % sub_folder)

# Patterns used to recognize interesting lines in an asciidoc source file.
# These patterns are only compiled once.

if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument('-diag', action='store', dest='diagFile',
                        help='Set the diagnostic file')
    parser.add_argument('-warn', action='store', dest='warnFile',
                        help='Set the warning file')
    parser.add_argument('-log', action='store', dest='logFile',
                        help='Set the log file for both diagnostics and warnings')
    parser.add_argument('-overwrite', action='store_true',
                        help='Overwrite input filenames instead of writing different output filenames')
    parser.add_argument('-out', action='store', dest='outDir',
                        default='out',
                        help='Set the output directory in which updated files are generated (default: out)')
    parser.add_argument('-suffix', action='store', dest='suffix',
                        default='',
                        help='Set the suffix added to updated file names (default: none)')
    parser.add_argument('files', metavar='filename', nargs='*',
                        help='a filename to promote text in')
    parser.add_argument('--version', action='version', version='%(prog)s 1.0')

    args = parser.parse_args()

    setLogFile(True,  True, args.logFile)
    setLogFile(True, False, args.diagFile)
    setLogFile(False, True, args.warnFile)

    if args.overwrite:
        logWarn('promote.py: will overwrite all input files')

    # If no files are specified, promote the entire specification chapters folder
    if len(args.files) == 0:
        folder_to_promote = os.getcwd()
        folder_to_promote += '/chapters'
        promoteAllAdocFiles(folder_to_promote, args)
    else:
        for file in args.files:
            promoteFile(file, args)

    print('At end, promoted interfaces remaining:')
    for key in promoted:
        if promoted[key]['extension'] != None:
            print('\t' + key)