# 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 datetime, 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',
        'namespace': 'gl',
        'enum_type': 'GLenum',
    },
    {
        'json': 'packed_egl_enums.json',
        'output': 'PackedEGLEnums',
        'namespace': 'egl',
        'enum_type': 'EGLenum',
    },
]


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.iteritems():

        values = []
        i = 0

        for (value_name, value_gl_name) in value_list.iteritems():
            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 {copyright_year} 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}_

#include <angle_gl.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>

#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, 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),
        copyright_year=datetime.date.today().year,
        data_source_name=data_source_name,
        script_name=sys.argv[0],
        file_name=file_name,
        include_guard=generate_include_guard(file_name),
        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 {copyright_year} 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),
        copyright_year=datetime.date.today().year,
        data_source_name=data_source_name,
        script_name=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']
        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, 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())
