#!/usr/bin/python
# Copyright 2016 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_format_map.py:
#  Code generation for GL format map. The format map matches between
#  {format,type} and internal format.
#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.

from datetime import date
import sys

sys.path.append('renderer')
import angle_format

template_cpp = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {data_source_name}.
// ES3 format info from {es3_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.
//
// format_map:
//   Determining the sized internal format from a (format,type) pair.
//   Also check es3 format combinations for validity.

#include "angle_gl.h"
#include "common/debug.h"

namespace gl
{{

GLenum GetSizedFormatInternal(GLenum format, GLenum type)
{{
    switch (format)
    {{
{format_cases}        case GL_NONE:
            return GL_NONE;

        default:
            break;
    }}

    return GL_NONE;
}}

bool ValidES3Format(GLenum format)
{{
    switch (format)
    {{
{es3_format_cases}            return true;

        default:
            return false;
    }}
}}

bool ValidES3Type(GLenum type)
{{
    switch (type)
    {{
{es3_type_cases}            return true;

        default:
            return false;
    }}
}}

bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat)
{{
    ASSERT(ValidES3Format(format) && ValidES3Type(type));

    switch (format)
    {{
{es3_combo_cases}        default:
            UNREACHABLE();
            break;
    }}

    return false;
}}

}}  // namespace gl
"""

template_format_case = """        case {format}:
            switch (type)
            {{
{type_cases}                default:
                    break;
            }}
            break;

"""

template_simple_case = """                case {key}:
                    return {result};
"""

template_es3_combo_type_case = """                case {type}:
                {{
                    switch (internalFormat)
                    {{
{internal_format_cases}                            return true;
                        default:
                            break;
                    }}
                    break;
                }}
"""


def parse_type_case(type, result):
    return template_simple_case.format(key=type, result=result)


def parse_format_case(format, type_map):
    type_cases = ""
    for type, internal_format in sorted(type_map.iteritems()):
        type_cases += parse_type_case(type, internal_format)
    return template_format_case.format(format=format, type_cases=type_cases)


def main():

    # auto_script parameters.
    if len(sys.argv) > 1:
        inputs = [
            'renderer/angle_format.py', 'es3_format_type_combinations.json', 'format_map_data.json'
        ]
        outputs = ['format_map_autogen.cpp']

        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

    input_script = 'format_map_data.json'

    format_map = angle_format.load_json(input_script)

    format_cases = ""

    for format, type_map in sorted(format_map.iteritems()):
        format_cases += parse_format_case(format, type_map)

    combo_data_file = 'es3_format_type_combinations.json'
    es3_combo_data = angle_format.load_json(combo_data_file)
    combo_data = [combo for sublist in es3_combo_data.values() for combo in sublist]

    types = set()
    formats = set()
    combos = {}

    for internal_format, format, type in combo_data:
        types.update([type])
        formats.update([format])
        if format not in combos:
            combos[format] = {}
        if type not in combos[format]:
            combos[format][type] = [internal_format]
        else:
            combos[format][type] += [internal_format]

    es3_format_cases = ""

    for format in sorted(formats):
        es3_format_cases += "        case " + format + ":\n"

    es3_type_cases = ""

    for type in sorted(types):
        es3_type_cases += "        case " + type + ":\n"

    es3_combo_cases = ""

    for format, type_combos in combos.iteritems():
        this_type_cases = ""
        for type, combos in type_combos.iteritems():
            internal_format_cases = ""
            for internal_format in combos:
                internal_format_cases += "                        case " + internal_format + ":\n"

            this_type_cases += template_es3_combo_type_case.format(
                type=type, internal_format_cases=internal_format_cases)

        es3_combo_cases += template_format_case.format(format=format, type_cases=this_type_cases)

    with open('format_map_autogen.cpp', 'wt') as out_file:
        output_cpp = template_cpp.format(
            script_name=sys.argv[0],
            data_source_name=input_script,
            es3_data_source_name=combo_data_file,
            copyright_year=date.today().year,
            format_cases=format_cases,
            es3_format_cases=es3_format_cases,
            es3_type_cases=es3_type_cases,
            es3_combo_cases=es3_combo_cases)
        out_file.write(output_cpp)
    return 0


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