#!/usr/bin/python3
# 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_copy_conversion_table.py:
#  Code generation for ES3 valid copy conversions table format map.
#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.

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}.
//
// 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.
//
// 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
{{

bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
{{
    switch (textureFormat)
    {{
{texture_format_cases}        default:
            break;
    }}

    return false;
}}

}}  // namespace gl
"""

template_format_case = """        case {texture_format}:
            switch (framebufferFormat)
            {{
{framebuffer_format_cases}                    return true;
                default:
                    break;
            }}
            break;

"""

template_simple_case = """                case {key}:
"""


def parse_texture_format_case(texture_format, framebuffer_formats):
    framebuffer_format_cases = ""
    for framebuffer_format in sorted(framebuffer_formats):
        framebuffer_format_cases += template_simple_case.format(key=framebuffer_format)
    return template_format_case.format(
        texture_format=texture_format, framebuffer_format_cases=framebuffer_format_cases)


def main():

    data_source_name = 'es3_copy_conversion_formats.json'
    out_file_name = 'es3_copy_conversion_table_autogen.cpp'

    # auto_script parameters.
    if len(sys.argv) > 1:
        inputs = ['renderer/angle_format.py', data_source_name]
        outputs = [out_file_name]

        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

    json_data = angle_format.load_json(data_source_name)

    format_map = {}

    for description, data in sorted(json_data.items()):
        for texture_format, framebuffer_format in data:
            if texture_format not in format_map:
                format_map[texture_format] = []
            format_map[texture_format] += [framebuffer_format]

    texture_format_cases = ""

    for texture_format, framebuffer_formats in sorted(format_map.items()):
        texture_format_cases += parse_texture_format_case(texture_format, framebuffer_formats)

    with open(out_file_name, 'wt') as out_file:
        output_cpp = template_cpp.format(
            script_name=sys.argv[0],
            data_source_name=data_source_name,
            texture_format_cases=texture_format_cases)
        out_file.write(output_cpp)
        out_file.close()
    return 0


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