'''
    Common GLES Subset Extraction Script
    ====================================

    In Kivy, our goal is to use OpenGL ES 2.0 (GLES2) for all drawing on all
    platforms. The problem is that GLES2 is not a proper subset of any OpenGL
    Desktop (GL) version prior to version 4.1.
    However, to keep all our drawing cross-platform compatible, we're
    restricting the Kivy drawing core to a real subset of GLES2 that is
    available on all platforms.

    This script therefore parses the GL and GL Extension (GLEXT) headers and
    compares them with the GLES2 header. It then generates a header that only
    contains symbols that are common to GLES2 and at least either GL or GLEXT.
    However, since GLES2 doesn't support double values, we also need to do some
    renaming, because functions in GL that took doubles as arguments now take
    floats in GLES2, with their function name being suffixed with 'f'.

    Furthermore, sometimes the pure symbol name doesn't match because there
    might be an _EXT or _ARB or something akin to that at the end of a symbol
    name. In that case, we take the symbol from the original header and add
    a #define directive to redirect to that symbol from the symbol name without
    extension.
'''

from __future__ import print_function

gl = open("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/" +
          "OpenGL.framework/Versions/A/Headers/gl.h", 'r')
glext = open("/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/" +
             "OpenGL.framework/Versions/A/Headers/glext.h", 'r')
gles = open("gl2.h", 'r')


def add_defines_to_set(header):
    symbols = []
    lineno = 0
    for line in header:
        symbol = None
        hexcode = None
        lineno += 1
        line = line.strip()
        try:
            elements = line.split()
            if line.startswith("#define"):
                symbol = elements[1]
                for element in elements:
                    if element.startswith("0x"):
                        hexcode = element
            elif line.startswith("typedef"):
                symbol = elements[-1]
            else:
                for element in elements:
                    if element.startswith("gl"):
                        symbol = element
            if symbol:
                symbols.append((symbol, lineno, line, hexcode))
        except Exception as e:
            print('error:', lineno, ':', line)
            print(e)

    return symbols


def extract_common_symbols(symbols1, symbols2, already_extracted):
    for symbol1, lineno1, line1, hexcode1 in symbols1:
        for symbol2, lineno2, line2, hexcode2 in symbols2:
            if symbol1 in already_extracted or symbol2 in already_extracted:
                continue
            if symbol1 == symbol2 + 'f':
                # There is no `double` type in GLES; Functions that were using
                # a double were renamed with the suffix 'f'.
                print("// Different Name; Redefine")
                print(line2)
                print("#define %s %s" % (symbol1, symbol2))
            elif symbol1 == symbol2:
                already_extracted.append(symbol1)
                print(line1)
                if symbol1 == 'GLclampf;':
                    # See explanation about doubles on GLES above.
                    print('typedef GLclampf GLclampd;')
            elif hexcode1 and hexcode2 and hexcode1 == hexcode2:
                already_extracted.append(symbol1)
                already_extracted.append(symbol2)
                print("// Different Name; Redefine")
                print(line2)
                print("#define %s %s" % (symbol1, symbol2))


# Generate ------------------------------------------------
# pipe to kivy/kivy/graphics/common_subset.h

gl_symbols = add_defines_to_set(gl)
glext_symbols = add_defines_to_set(glext)
gles_symbols = add_defines_to_set(gles)

print('// GLES 2.0 Header file, generated for Kivy')
print('// Check kivy/kivy/tools/gles_compat/subset_gles.py')
print('#pragma once')
print('#include "gl2platform.h"')
print('#ifdef __cplusplus')
print('extern "C" {')
print('#endif')

# Don't add the same symbol more than once
already_extracted = []

print('\n// Subset common to GLES and GL: ===================================')
extract_common_symbols(gles_symbols, gl_symbols, already_extracted)

print('\n// Subset common to GLES and GLEXT: ================================')
extract_common_symbols(gles_symbols, glext_symbols, already_extracted)

print()
print('// What follows was manually extracted from the GLES2 headers because')
print('// it was not present in any other header.', end=' ')
print('''
#define GL_SHADER_BINARY_FORMATS          0x8DF8
#define GL_RGB565                         0x8D62
''')

print('#ifdef __cplusplus')
print('}')
print('#endif')
print('\n')
