#!/usr/bin/env python3
import sys
import string
import argparse
import os

def camel_case(str_):
    """Convert snake_case to CamelCase."""
    return string.capwords(str_, "_").replace("_", "")

def main():
    # Set up argument parser
    parser = argparse.ArgumentParser(description='Generate configuration files for Hermes.')
    parser.add_argument('input_template', 
                        type=argparse.FileType('r'),
                        help='Input configuration template file')
    parser.add_argument('--html-template', 
                        default='',
                        help='Path to HTML template input file')
    parser.add_argument('--cpp-template', 
                        default='',
                        help='Path to C++ template input file')
    parser.add_argument('--h-template', 
                        default='',
                        help='Path to header template input file')
    parser.add_argument('--output-cpp', 
                        default='',
                        help='Output path for generated C++ file')
    parser.add_argument('--output-h', 
                        default='',
                        help='Output path for generated header file')
    parser.add_argument('--output-example', 
                        default='',
                        help='Output path for example configuration')
    parser.add_argument('--output-html', 
                        default='',
                        help='Output path for generated HTML documentation')

    # Parse arguments
    args = parser.parse_args()

    hvar1 = []
    hvar2 = []
    cppvar1 = []
    cppvar2 = []
    cppvar3 = []
    conf_example = []
    htmlvar = []
    htmlexpl = ""

    # Process input
    for line in args.input_template:
        line = line.strip()
        
        if not line or line.startswith('#') or line.startswith('*'):
            if line == '*clean*':
                htmlexpl = ""
            elif line.startswith('*'):
                line = line.replace('*', '#').strip()
                conf_example.append(line)
                
                # Convert line for HTML
                line_html = line.lstrip('#').replace('>', '>')
                htmlexpl += line_html + "\n"
            continue

        parts = line.split(',')
        parts = [p.strip() for p in parts]

        type_str = parts[0]
        var_name = parts[1]
        default_val = parts[2]

        # Modify type for lists
        if 'list' in type_str:
            type_str = 'list<string>'

        camel_name = camel_case(var_name)

        # Generate header variables
        hvar1.append(f"{type_str} {var_name};")
        hvar2.append(f"{type_str}& get{camel_name}();")

        # Generate cpp variables
        if 'list' in type_str:
            cppvar1.append(f"{var_name} = Configfile::parseAsList({default_val});")
        else:
            cppvar1.append(f"{var_name} = {default_val};")

        cppvar2.append(f"PARSE_{parts[0].upper()}(\"{var_name}\", {var_name})")
        cppvar3.append(f"GET_VAR(get{camel_name}, {var_name}, {type_str}&)")

        # Generate config example
        conf_example.append(f"{var_name} = {default_val}")

        # Generate HTML
        if args.html_template:
            html_templ = open(args.html_template, 'r').read()
            html_temp = html_templ.replace('%type%', parts[0]) \
                                  .replace('%name%', var_name) \
                                  .replace('%default%', default_val) \
                                  .replace('%explanation%', htmlexpl)
            htmlvar.append(html_temp)
        htmlexpl = ""

    # Convert lists to newline-separated strings
    hvar1 = '\n'.join(hvar1)
    hvar2 = '\n'.join(hvar2)
    cppvar1 = '\n'.join(cppvar1)
    cppvar2 = '\n'.join(cppvar2)
    cppvar3 = '\n'.join(cppvar3)
    conf_example = '\n\n'.join(conf_example)
    htmlvar = ''.join(htmlvar)

    # Write Configfile.cpp
    if args.cpp_template and args.output_cpp:
        try:
            cpp_str = open(args.cpp_template, 'r').read()
            cpp_str = cpp_str.replace('%templ_default_values%', cppvar1) \
                             .replace('%templ_parsevars%', cppvar2) \
                             .replace('%templ_getmethods%', cppvar3)

            os.makedirs(os.path.dirname(args.output_cpp), exist_ok=True)
            with open(args.output_cpp, 'w') as f:
                f.write(cpp_str)
        except FileNotFoundError:
            print(f"Error: C++ template file {args.cpp_template} not found.", file=sys.stderr)
            sys.exit(1)

    # Write Configfile.h
    if args.h_template and args.output_h:
        try:
            h_str = open(args.h_template, 'r').read()
            h_str = h_str.replace('%templ_privateattribs%', hvar1) \
                         .replace('%templ_publicmethods%', hvar2)

            os.makedirs(os.path.dirname(args.output_h), exist_ok=True)
            with open(args.output_h, 'w') as f:
                f.write(h_str)
        except FileNotFoundError:
            print(f"Error: Header template file {args.h_template} not found.", file=sys.stderr)
            sys.exit(1)

    # Write hermesrc.example
    if args.output_example:
        os.makedirs(os.path.dirname(args.output_example), exist_ok=True)
        with open(args.output_example, 'w') as f:
            f.write(conf_example)

    # Write hermes-options.html
    if args.output_html and htmlvar:
        os.makedirs(os.path.dirname(args.output_html), exist_ok=True)
        with open(args.output_html, 'w') as f:
            f.write(htmlvar)

if __name__ == "__main__":
    main()