# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

import runpy
import sys
import string
import argparse


class PropertyWrapper(object):
    __slots__ = ["index", "prop", "idlname"]

    def __init__(self, index, prop):
        self.index = index
        self.prop = prop
        if "Internal" in prop.flags:
            self.idlname = None
        else:
            idl_name = prop.method
            if not idl_name.startswith("Moz"):
                idl_name = idl_name[0].lower() + idl_name[1:]
            self.idlname = idl_name

    def __getattr__(self, name):
        return getattr(self.prop, name)


def generate(output, dataFile):
    output.write(
        """/* THIS IS AN AUTOGENERATED FILE.  DO NOT EDIT */

/* processed file that defines CSS property tables that can't be generated
   with the pre-processor, designed to be #included in nsCSSProps.cpp */

"""
    )

    raw_properties = runpy.run_path(dataFile)["data"]
    properties = [
        PropertyWrapper(i, p)
        for i, p in enumerate(raw_properties)
        if p.type() != "alias"
    ]

    # Generate kIDLNameTable
    output.write(
        "const char* const nsCSSProps::" "kIDLNameTable[eCSSProperty_COUNT] = {\n"
    )
    for p in properties:
        if p.idlname is None:
            output.write("  nullptr,  // {}\n".format(p.name))
        else:
            output.write('  "{}",\n'.format(p.idlname))
    output.write("};\n\n")

    # Generate kIDLNameSortPositionTable
    ps = sorted(properties, key=lambda p: p.idlname if p.idlname else "")
    ps = [(p, position) for position, p in enumerate(ps)]
    ps.sort(key=lambda item: item[0].index)
    output.write(
        "const int32_t nsCSSProps::"
        "kIDLNameSortPositionTable[eCSSProperty_COUNT] = {\n"
    )
    for (p, position) in ps:
        output.write("  {},\n".format(position))
    output.write("};\n\n")

    # Generate preferences table
    output.write(
        "const nsCSSProps::PropertyPref " "nsCSSProps::kPropertyPrefTable[] = {\n"
    )
    for p in raw_properties:
        if not p.pref:
            continue
        if p.type() != "alias":
            prop_id = "eCSSProperty_" + p.id
        else:
            prop_id = "eCSSPropertyAlias_" + p.alias_id
        output.write('  {{ {}, "{}" }},\n'.format(prop_id, p.pref))
    output.write("  { eCSSProperty_UNKNOWN, nullptr },\n")
    output.write("};\n\n")

    # Generate shorthand subprop tables
    names = []
    for p in properties:
        if p.type() != "shorthand":
            continue
        name = "g{}SubpropTable".format(p.method)
        names.append(name)
        output.write("static const nsCSSPropertyID {}[] = {{\n".format(name))
        for subprop in p.subprops:
            output.write("  eCSSProperty_{},\n".format(subprop))
        output.write("  eCSSProperty_UNKNOWN\n")
        output.write("};\n\n")
    output.write("const nsCSSPropertyID* const\n")
    output.write(
        "nsCSSProps::kSubpropertyTable["
        "eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands"
        "] = {\n"
    )
    for name in names:
        output.write("  {},\n".format(name))
    output.write("};\n\n")

    # Generate assertions
    msg = (
        "GenerateCSSPropsGenerated.py did not list properties "
        "in nsCSSPropertyID order"
    )
    for p in properties:
        output.write(
            'static_assert(eCSSProperty_{} == {}, "{}");\n'.format(p.id, p.index, msg)
        )
