# Copyright (c) 2019 Nordic Semiconductor ASA
# Copyright (c) 2019 Linaro Limited
# Copyright (c) 2018..2020 Bobby Noelte.
# SPDX-License-Identifier: BSD-3-Clause

import cogeno

##
# @brief Converts 's' to a form suitable for (part of) an identifier.
#
# @param s string
def str2ident(s):
    return s.replace("-", "_") \
            .replace(",", "_") \
            .replace("@", "_") \
            .replace("/", "_") \
            .replace(".", "_") \
            .replace("+", "PLUS") \
            .upper()

##
# @brief Write #if guard for config property to output.
#
# @param property_name Property name
def outl_config_guard(property_name):
    is_config = cogeno.config_property(property_name, 0)
    cogeno.outl("#if {} // Guard({}) {}".format(
        is_config, is_config, property_name))

##
# @brief Write #endif guard for config property to output.
#
# @param property_name Property name
def outl_config_unguard(property_name):
    is_config = cogeno.config_property(property_name, 0)
    cogeno.outl("#endif // Guard({}) {}".format(is_config, property_name))


##
# @brief Write 's' as a comment.
#
# @param s string, is allowed to have multiple lines.
# @param blank_before True adds a blank line before the comment.
def out_comment(s, blank_before=True):
    if blank_before:
        cogeno.outl("")

    if "\n" in s:
        # Format multi-line comments like
        #
        #   /*
        #    * first line
        #    * second line
        #    *
        #    * empty line before this line
        #    */
        res = ["/*"]
        for line in s.splitlines():
            # Avoid an extra space after '*' for empty lines. They turn red in
            # Vim if space error checking is on, which is annoying.
            res.append(" *" if not line.strip() else " * " + line)
        res.append(" */")
        cogeno.out("\n".join(res))
    else:
        # Format single-line comments like
        #
        #   /* foo bar */
        cogeno.out("/* " + s + " */")


##
# @brief Writes an overview comment with misc. info about EDTS.
def out_edts_comment_overview():
    edts = cogeno.edts()

    s = f"""\
Generated by cogeno.py

DTS input file:
  {edts.dts_path()}

Directories with bindings:
  {", ".join(edts.bindings_dirs())}

Nodes in dependency order (ordinal and path):
"""

    out_comment(s, blank_before=False)


# Writes a comment describing 'device'
def out_edts_comment_device(device_id):
    edts = cogeno.edts()

    s = f"""\
Devicetree node:
  {edts.device_property(device_id, 'path')}
"""

    out_comment(s)

##
# @brief Write EDTS database properties as C defines.
#
# @param prefix Define label prefix. Default is 'EDT_'.
def outl_edts_defines(prefix = 'EDT_'):
    out_edts_comment_overview()

    out_comment("Compatibles")
    for compatible, compatible_devices in cogeno.edts().compatibles().items():
        for index, compatible_ref in compatible_devices.items():
            define_label = str2ident("{}COMPATIBLE_{}_{}".format(
                prefix, compatible, index))
            if index == 'count':
                define_value = compatible_ref
            else:
                define_value = str2ident(prefix + compatible_ref)
            cogeno.outl("#define {}\t{}".format(define_label, define_value))

    out_comment("Devices")
    for device_id in cogeno.edts()['devices']:
        properties = cogeno.edts().device_properties_flattened(device_id)
        out_edts_comment_device(device_id)
        for prop_path, prop_value in properties.items():
            define_label = str2ident("{}{}_{}".format(prefix, device_id,
                                                      prop_path))
            if prop_value in cogeno.edts()['devices']:
                # Property value is a device-id
                prop_value = str2ident("{}{}".format(prefix, prop_value))
            cogeno.outl("#define {}\t{}".format(define_label, prop_value))
