#/usr/bin/python3

# IDL to Cpp/H by Alter with ChatGPT assistance. Or vice versa ;)
# (L) 2023.05.05
# Use it for your own risk :)

import re
import sys

def process_match(match, class_name, prefix=None):
    method_name = match.group(1)
    params = match.group(2)
    params = re.sub(r'\[in\]|\[out\]|\[retval\]|\[out,\s*retval\]', '', params).strip()

    if prefix:
        method_name = f'{prefix}_{method_name}'

    return (f'public:\n    STDMETHOD({method_name})({params});',
            f'STMETHODIMP {class_name}::{method_name}({params})\n{\n}')
#end process_match()


def idl_to_cpp(input_str, class_name):
    patterns = [
        (r'\[id\(\d+\),\s*helpstring\("method[\w\s]+"\)\]\s*HRESULT\s+([\w]+)\((.*)\);', None),
        (r'\[propget,\s*id\(\d+\),\s*helpstring\("property[\w\s]+"\)\]\s*HRESULT\s+([\w]+)\((.*)\);', 'get'),
        (r'\[propput,\s*id\(\d+\),\s*helpstring\("property[\w\s]+"\)\]\s*HRESULT\s+([\w]+)\((.*)\);', 'put')
    ]

    for pattern, prefix in patterns:
        match = re.search(pattern, input_str)
        if match:
            cpp_h_output, cpp_cpp_output = process_match(match, class_name, prefix)
            return cpp_h_output, cpp_cpp_output

    return "Invalid input format.", "Invalid input format."
#end idl_to_cpp()


'''
# Example usage
idl_input = '[propget, id(13), helpstring("property MyProperty")] HRESULT MyProperty([out, retval] LONG* pVal);'
#idl_input = '[id(42), helpstring("method My Method")] HRESULT MyMethod([in] IMyObject* pObject, [in] enum MyOptionCode);'
class_name = "MyClass"
'''
try:
    class_name = sys.argv[1]
    idl_input = sys.argv[2]

    cpp_h_output, cpp_cpp_output = idl_to_cpp(idl_input, class_name)

    print("Header (.h) code:")
    print(cpp_h_output)
    print("\nSource (.cpp) code:")
    print(cpp_cpp_output)

except:
    print("Usage:")
    print("  idl2cpp.py <Target Class Name>  '<IDL definition>'")
    print("Example:")
    print('  idl2cpp.py MyClass \'[propget, id(13), helpstring("property MyProperty")] HRESULT MyProperty([out, retval] LONG* pVal\');')
#end try
