# brushlib - The MyPaint Brush Library
# Copyright (C) 2007-2008 Martin Renold <martinxyz@gmx.ch>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"Code generator, part of the build process."
import os
import sys
import gettext
if os.path.exists("brushlib"):
    sys.path.append("brushlib")
import brushsettings
from os.path import basename


# workaround for https://gna.org/bugs/index.php?20281
def do_not_translate(domain, s):
    return s

gettext.dgettext = do_not_translate


def writefile(filename, s):
    "write generated code if changed"
    bn = basename(sys.argv[0])
    s = '// DO NOT EDIT - autogenerated by ' + bn + '\n\n' + s
    if os.path.exists(filename) and open(filename).read() == s:
        print 'Checked', filename
    else:
        print 'Writing', filename
        open(filename, 'w').write(s)


def generate_enum(enum_name, enum_prefix, count_name, name_list, value_list):
    # Can only generate an enum which starts at 0, and where each value is 1 more than the former
    assert len(name_list) == len(value_list)
    assert value_list == list(xrange(0, len(value_list)))

    indent = " " * 4
    begin = "typedef enum {\n"
    end = "} %s;\n" % enum_name

    entries = []
    for name in name_list:
        entries.append(indent + enum_prefix + name)
    entries.append(indent + count_name)

    return begin + ",\n".join(entries) + "\n" + end


def generate_static_struct_array(struct_type, instance_name, entries_list):

    indent = " " * 4
    begin = "static %s %s[] = {\n" % (struct_type, instance_name)
    end = "};\n"

    entries = []
    for entry in entries_list:
        entries.append(indent + "{%s}" % (", ".join(entry)))
    entries.append("\n")

    return begin + ", \n".join(entries) + end


def generate_internal_settings_code():
    content = ''

    def stringify(value):
        value = value.replace("\n", "\\n")
        value = value.replace('"', '\\"')
        return "\"%s\"" % value

    def floatify(value, positive_inf=True):
        if value is None:
            return "FLT_MAX" if positive_inf else "-FLT_MAX"

        return str(value)

    def gettextify(value):
        return "N_(%s)" % stringify(value)

    def boolify(value):
        return str("TRUE") if value else str("FALSE")

    def input_info_struct(i):
        return (stringify(i.name), floatify(i.hard_min), floatify(i.soft_min),
                floatify(i.normal), floatify(i.soft_max), floatify(i.hard_max),
                gettextify(i.dname), gettextify(i.tooltip))

    def settings_info_struct(s):
        return (stringify(s.cname), gettextify(s.name), boolify(s.constant),
                floatify(s.min), floatify(s.default), floatify(s.max), gettextify(s.tooltip))

    content += generate_static_struct_array("MyPaintBrushSettingInfo", "settings_info_array",
                                            [settings_info_struct(i) for i in brushsettings.settings])
    content += "\n"
    content += generate_static_struct_array("MyPaintBrushInputInfo", "inputs_info_array",
                                            [input_info_struct(i) for i in brushsettings.inputs])

    return content


def generate_public_settings_code():
    content = ''

    content += generate_enum("MyPaintBrushInput", "MYPAINT_BRUSH_INPUT_", "MYPAINT_BRUSH_INPUTS_COUNT",
                             [i.name.upper() for i in brushsettings.inputs],
                             [i.index for i in brushsettings.inputs])
    content += '\n'
    content += generate_enum("MyPaintBrushSetting", "MYPAINT_BRUSH_SETTING_", "MYPAINT_BRUSH_SETTINGS_COUNT",
                             [i.cname.upper() for i in brushsettings.settings],
                             [i.index for i in brushsettings.settings])
    content += '\n'
    content += generate_enum("MyPaintBrushState", "MYPAINT_BRUSH_STATE_", "MYPAINT_BRUSH_STATES_COUNT",
                             [i.cname.upper() for i in brushsettings.states],
                             [i.index for i in brushsettings.states])
    content += '\n'

    return content


if __name__ == '__main__':

    args = sys.argv[1:]

    writefile(args[0], generate_public_settings_code())
    writefile(args[1], generate_internal_settings_code())
