#!/usr/bin/env python2
# Copyright 2019 The Dawn Authors
#
# Licensed 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.

import os, sys
from collections import namedtuple
import xml.etree.ElementTree as etree

from generator_lib import Generator, run_generator, FileRender

class ProcName:
    def __init__(self, gl_name, proc_name=None):
        assert(gl_name.startswith('gl'))
        if proc_name == None:
            proc_name = gl_name[2:]

        self.gl_name = gl_name
        self.proc_name = proc_name

    def glProcName(self):
        return self.gl_name

    def ProcName(self):
        return self.proc_name

    def PFNPROCNAME(self):
        return 'PFN' + self.gl_name.upper() + 'PROC'

    def __repr__(self):
        return 'Proc("{}", "{}")'.format(self.gl_name, self.proc_name)

ProcParam = namedtuple('ProcParam', ['name', 'type'])
class Proc:
    def __init__(self, element):
        # Type declaration for return values and arguments all have the same
        # (weird) format.
        # <element>[A][<ptype>B</ptype>][C]<other stuff.../></element>
        #
        # Some examples are:
        #   <proto>void <name>glFinish</name></proto>
        #   <proto><ptype>GLenum</ptype><name>glFenceSync</name></proto>
        #   <proto>const <ptype>GLubyte</ptype> *<name>glGetString</name></proto>
        #
        # This handles all the shapes found in gl.xml except for this one that
        # has an array specifier after </name>:
        #   <param><ptype>GLuint</ptype> <name>baseAndCount</name>[2]</param>
        def parse_type_declaration(element):
            result = ''
            if element.text != None:
                result += element.text
            ptype = element.find('ptype')
            if ptype != None:
                result += ptype.text
                if ptype.tail != None:
                    result += ptype.tail
            return result.strip()

        proto = element.find('proto')

        self.return_type = parse_type_declaration(proto)

        self.params = []
        for param in element.findall('./param'):
            self.params.append(ProcParam(param.find('name').text, parse_type_declaration(param)))

        self.gl_name = proto.find('name').text
        self.alias = None
        if element.find('alias') != None:
            self.alias = element.find('alias').attrib['name']

    def glProcName(self):
        return self.gl_name

    def ProcName(self):
        assert(self.gl_name.startswith('gl'))
        return self.gl_name[2:]

    def PFNGLPROCNAME(self):
        return 'PFN' + self.gl_name.upper() + 'PROC'

    def __repr__(self):
        return 'Proc("{}")'.format(self.gl_name)

EnumDefine = namedtuple('EnumDefine', ['name', 'value'])
Version = namedtuple('Version', ['major', 'minor'])
VersionBlock = namedtuple('VersionBlock', ['version', 'procs', 'enums'])
HeaderBlock = namedtuple('HeaderBlock', ['description', 'procs', 'enums'])

def parse_version(version):
    return Version(*map(int, version.split('.')))


def compute_params(root):
    # Parse all the commands and enums
    all_procs = {}
    for command in root.findall('''commands[@namespace='GL']/command'''):
        proc = Proc(command)
        assert(proc.gl_name not in all_procs)
        all_procs[proc.gl_name] = proc

    all_enums = {}
    for enum in root.findall('''enums[@namespace='GL']/enum'''):
        enum_name = enum.attrib['name']
        # Special case an enum we'll never use that has different values in GL and GLES
        if enum_name == 'GL_ACTIVE_PROGRAM_EXT':
            continue

        assert(enum_name not in all_enums)
        all_enums[enum_name] = EnumDefine(enum_name, enum.attrib['value'])

    # Get the list of all Desktop OpenGL function removed by the Core Profile.
    core_removed_procs = set()
    for proc in root.findall('''feature/remove[@profile='core']/command'''):
        core_removed_procs.add(proc.attrib['name'])

    # Get list of enums and procs per OpenGL ES/Desktop OpenGL version
    def parse_version_blocks(api, removed_procs = set()):
        blocks = []
        for section in root.findall('''feature[@api='{}']'''.format(api)):
            section_procs = []
            for command in section.findall('./require/command'):
                proc_name = command.attrib['name']
                assert(all_procs[proc_name].alias == None)
                if proc_name not in removed_procs:
                    section_procs.append(all_procs[proc_name])

            section_enums = []
            for enum in section.findall('./require/enum'):
                section_enums.append(all_enums[enum.attrib['name']])

            blocks.append(VersionBlock(parse_version(section.attrib['number']), section_procs, section_enums))

        return blocks

    gles_blocks = parse_version_blocks('gles2')
    desktop_gl_blocks = parse_version_blocks('gl', core_removed_procs)

    # Compute the blocks for headers such that there is no duplicate definition
    already_added_header_procs = set()
    already_added_header_enums = set()
    header_blocks = []
    def add_header_block(description, block):
        block_procs = []
        for proc in block.procs:
            if not proc.glProcName() in already_added_header_procs:
                already_added_header_procs.add(proc.glProcName())
                block_procs.append(proc)

        block_enums = []
        for enum in block.enums:
            if not enum.name in already_added_header_enums:
                already_added_header_enums.add(enum.name)
                block_enums.append(enum)

        if len(block_procs) > 0 or len(block_enums) > 0:
            header_blocks.append(HeaderBlock(description, block_procs, block_enums))

    for block in gles_blocks:
        add_header_block('OpenGL ES {}.{}'.format(block.version.major, block.version.minor), block)

    for block in desktop_gl_blocks:
        add_header_block('Desktop OpenGL {}.{}'.format(block.version.major, block.version.minor), block)

    return {
        'gles_blocks': gles_blocks,
        'desktop_gl_blocks': desktop_gl_blocks,
        'header_blocks': header_blocks,
    }

class OpenGLLoaderGenerator(Generator):
    def get_description(self):
        return 'Generates code to load OpenGL function pointers'

    def add_commandline_arguments(self, parser):
        parser.add_argument('--gl-xml', required=True, type=str, help ='The Khronos gl.xml to use.')

    def get_file_renders(self, args):
        params = compute_params(etree.parse(args.gl_xml).getroot())

        return [
            FileRender('opengl/OpenGLFunctionsBase.cpp', 'dawn_native/opengl/OpenGLFunctionsBase_autogen.cpp', [params]),
            FileRender('opengl/OpenGLFunctionsBase.h', 'dawn_native/opengl/OpenGLFunctionsBase_autogen.h', [params]),
            FileRender('opengl/opengl_platform.h', 'dawn_native/opengl/opengl_platform_autogen.h', [params]),
        ]

    def get_dependencies(self, args):
        return [os.path.abspath(args.gl_xml)]

if __name__ == '__main__':
    sys.exit(run_generator(OpenGLLoaderGenerator()))
