#!/usr/bin/python3
# Copyright 2018 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# gen_packed_gl_enums.py:
#   Code generation for the packed enums.
#   NOTE: don't run this script directly. Run scripts/run_code_generation.py.

import json, os, sys
from collections import namedtuple
from collections import OrderedDict

Enum = namedtuple('Enum', ['name', 'values', 'max_value'])
EnumValue = namedtuple('EnumValue', ['name', 'gl_name', 'value'])

Generators = [
    {
        'json': 'packed_gl_enums.json',
        'output': 'PackedGLEnums',
        'includes': '#include <angle_gl.h>',
        'namespace': 'gl',
        'enum_type': 'GLenum',
    },
    {
        'json': 'packed_egl_enums.json',
        'output': 'PackedEGLEnums',
        'includes': '#include <EGL/egl.h>\n#include <EGL/eglext.h>',
        'namespace': 'egl',
        'enum_type': 'EGLenum',
    },
    {
        'json': 'packed_cl_enums.json',
        'output': 'PackedCLEnums',
        'includes': '#include <angle_cl.h>\ntypedef cl_uint CLenum;',
        'namespace': 'cl',
        'enum_type': 'CLenum',
    },
]


def load_enums(path):
    with open(path) as map_file:
        enums_dict = json.loads(map_file.read(), object_pairs_hook=OrderedDict)

    enums = []
    for (enum_name, value_list) in enums_dict.items():

        values = []
        i = 0

        for (value_name, value_gl_name) in value_list.items():
            values.append(EnumValue(value_name, value_gl_name, i))
            i += 1

        assert (i < 255)  # This makes sure enums fit in the uint8_t
        enums.append(Enum(enum_name, values, i))

    enums.sort(key=lambda enum: enum.name)
    return enums


def generate_include_guard(path):
    return path.replace(".", "_").upper()


def header_name_from_cpp_name(path):
    return path.replace(".cpp", ".h")


header_template = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {data_source_name}.
//
// Copyright 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// {file_name}:
//   Declares ANGLE-specific enums classes for {api_enum_name}s and functions operating
//   on them.

#ifndef COMMON_{include_guard}_
#define COMMON_{include_guard}_

{includes}

#include <cstdint>
#include <ostream>

namespace {namespace}
{{

template<typename Enum>
Enum From{api_enum_name}({api_enum_name} from);
{content}
}}  // namespace {namespace}

#endif // COMMON_{include_guard}_
"""

enum_declaration_template = """
enum class {enum_name} : uint8_t
{{
{value_declarations}

    InvalidEnum = {max_value},
    EnumCount = {max_value},
}};

template <>
{enum_name} From{api_enum_name}<{enum_name}>({api_enum_name} from);
{api_enum_name} To{api_enum_name}({enum_name} from);
std::ostream &operator<<(std::ostream &os, {enum_name} value);
"""


def write_header(enums, path_prefix, file_name, data_source_name, includes, namespace,
                 api_enum_name):
    content = ['']

    for enum in enums:
        value_declarations = []
        for value in enum.values:
            value_declarations.append('    ' + value.name + ' = ' + str(value.value) + ',')

        content.append(
            enum_declaration_template.format(
                enum_name=enum.name,
                max_value=str(enum.max_value),
                value_declarations='\n'.join(value_declarations),
                api_enum_name=api_enum_name))

    header = header_template.format(
        content=''.join(content),
        data_source_name=data_source_name,
        script_name=os.path.basename(sys.argv[0]),
        file_name=file_name,
        include_guard=generate_include_guard(file_name),
        includes=includes,
        namespace=namespace,
        api_enum_name=api_enum_name)

    with (open(path_prefix + file_name, 'wt')) as f:
        f.write(header)


cpp_template = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {data_source_name}.
//
// Copyright 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// {file_name}:
//   Implements ANGLE-specific enums classes for {api_enum_name}s and functions operating
//   on them.

#include "common/debug.h"
#include "common/{header_name}"

namespace {namespace}
{{
{content}
}}  // namespace {namespace}
"""

enum_implementation_template = """
template <>
{enum_name} From{api_enum_name}<{enum_name}>({api_enum_name} from)
{{
    switch (from)
    {{
{from_glenum_cases}
        default:
            return {enum_name}::InvalidEnum;
    }}
}}

{api_enum_name} To{api_enum_name}({enum_name} from)
{{
    switch (from)
    {{
{to_glenum_cases}
        default:
            UNREACHABLE();
            return 0;
    }}
}}

std::ostream &operator<<(std::ostream &os, {enum_name} value)
{{
    switch (value)
    {{
{ostream_cases}
        default:
            os << "GL_INVALID_ENUM";
            break;
    }}
    return os;
}}
"""


def write_cpp(enums, path_prefix, file_name, data_source_name, namespace, api_enum_name):
    content = ['']

    for enum in enums:
        from_glenum_cases = []
        to_glenum_cases = []
        ostream_cases = []
        for value in enum.values:
            qualified_name = enum.name + '::' + value.name
            from_glenum_cases.append('        case ' + value.gl_name + ':\n            return ' +
                                     qualified_name + ';')
            to_glenum_cases.append('        case ' + qualified_name + ':\n            return ' +
                                   value.gl_name + ';')
            ostream_cases.append('        case ' + qualified_name + ':\n            os << "' +
                                 value.gl_name + '";\n            break;')

        content.append(
            enum_implementation_template.format(
                enum_name=enum.name,
                from_glenum_cases='\n'.join(from_glenum_cases),
                max_value=str(enum.max_value),
                to_glenum_cases='\n'.join(to_glenum_cases),
                api_enum_name=api_enum_name,
                ostream_cases='\n'.join(ostream_cases)))

    cpp = cpp_template.format(
        content=''.join(content),
        data_source_name=data_source_name,
        script_name=os.path.basename(sys.argv[0]),
        file_name=file_name,
        header_name=header_name_from_cpp_name(file_name),
        namespace=namespace,
        api_enum_name=api_enum_name)

    with (open(path_prefix + file_name, 'wt')) as f:
        f.write(cpp)


def main():

    # auto_script parameters.
    if len(sys.argv) > 1:
        inputs = []
        outputs = []
        for generator in Generators:
            inputs += [generator['json']]
            outputs += [
                generator['output'] + '_autogen.cpp',
                generator['output'] + '_autogen.h',
            ]

        if sys.argv[1] == 'inputs':
            print(','.join(inputs))
        elif sys.argv[1] == 'outputs':
            print(','.join(outputs))
        else:
            print('Invalid script parameters')
            return 1
        return 0

    path_prefix = os.path.dirname(os.path.realpath(__file__)) + os.path.sep

    for generator in Generators:
        json_file = generator['json']
        output_file = generator['output']
        includes = generator['includes']
        namespace = generator['namespace']
        enum_type = generator['enum_type']
        enums = load_enums(path_prefix + json_file)
        write_header(enums, path_prefix, output_file + '_autogen.h', json_file, includes,
                     namespace, enum_type)
        write_cpp(enums, path_prefix, output_file + '_autogen.cpp', json_file, namespace,
                  enum_type)
    return 0


if __name__ == '__main__':
    sys.exit(main())
