# Copyright (c) 2020 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

"""
Like gen_kconfig_rest.py, but for generating an index of existing
devicetree bindings.
"""

import argparse
from collections import defaultdict
import glob
import io
import logging
import os
from pathlib import Path
import pprint
import re
import sys
import textwrap

import edtlib

import gen_helpers

# A line of '-' characters in vendor-prefixes.txt that separates
# the data from comments about it.
VENDOR_PREFIXES_SEPARATOR = '-' * 50

ZEPHYR_BASE = Path(__file__).parents[2]

GENERIC_OR_VENDOR_INDEPENDENT = 'Generic or vendor-independent'
UNKNOWN_VENDOR = 'Unknown vendor'

ZEPHYR_BASE = Path(__file__).parents[2]

# Base properties that have documentation in 'dt-important-props'.
DETAILS_IN_IMPORTANT_PROPS = set('compatible label reg status interrupts'.split())

logger = logging.getLogger('gen_devicetree_rest')

class VndLookup:
    """
    A convenience class for looking up information based on a
    devicetree compatible's vendor prefix 'vnd'.
    """

    def __init__(self, vendor_prefixes, bindings):
        self.vnd2vendor = self.load_vnd2vendor(vendor_prefixes)
        self.vnd2bindings = self.init_vnd2bindings(bindings)
        self.vnd2ref_target = self.init_vnd2ref_target()

    def vendor(self, vnd):
        return self.vnd2vendor.get(vnd, UNKNOWN_VENDOR)

    def bindings(self, vnd, default=None):
        return self.vnd2bindings.get(vnd, default)

    def target(self, vnd):
        return self.vnd2ref_target.get(
            vnd, self.vnd2ref_target[(UNKNOWN_VENDOR,)])

    @staticmethod
    def load_vnd2vendor(vendor_prefixes):
        # Load the vendor-prefixes.txt file. Return a dict mapping 'vnd'
        # vendor prefixes as they are found in compatible properties to
        # each vendor's full name.
        #
        # For example, this line:
        #
        #    vnd	A stand-in for a real vendor
        #
        # Gets split into a key 'vnd' and a value 'A stand-in for a real
        # vendor' in the return value.
        #
        # The 'None' key maps to GENERIC_OR_VENDOR_INDEPENDENT.

        vnd2vendor = {
            None: GENERIC_OR_VENDOR_INDEPENDENT,
        }
        found_separator = False     # have we found the '-----' separator?
        with open(vendor_prefixes, 'r') as f:
            for line in f:
                line = line.strip()
                if line and found_separator:
                    # Every line after the separator should be in this form:
                    #
                    # <vnd><TAB><vendor>
                    vnd_vendor = line.split('\t', 1)
                    assert len(vnd_vendor) == 2, line
                    vnd2vendor[vnd_vendor[0]] = vnd_vendor[1]
                elif line.startswith(VENDOR_PREFIXES_SEPARATOR):
                    found_separator = True

        logger.info('found %d vendor prefixes in %s', len(vnd2vendor) - 1,
                    vendor_prefixes)
        if logger.isEnabledFor(logging.DEBUG):
            logger.debug('vnd2vendor=%s', pprint.pformat(vnd2vendor))

        return vnd2vendor

    def init_vnd2bindings(self, bindings):
        # Take a 'vnd2vendor' map and a list of bindings and return a dict
        # mapping 'vnd' vendor prefixes prefixes to lists of bindings. The
        # bindings in each list are sorted by compatible. The keys in the
        # return value are sorted by vendor name.
        #
        # Special cases:
        #
        # - The 'None' key maps to bindings with no vendor prefix
        #   in their compatibles, like 'gpio-keys'. This is the first key.
        # - The (UNKNOWN_VENDOR,) key maps to bindings whose compatible
        #   has a vendor prefix that exists, but is not known,
        #   like 'somethingrandom,device'. This is the last key.

        # Get an unsorted dict mapping vendor prefixes to lists of bindings.
        unsorted = defaultdict(list)
        generic_bindings = []
        unknown_vendor_bindings = []
        for binding in bindings:
            vnd = compatible_vnd(binding.compatible)
            if vnd is None:
                generic_bindings.append(binding)
            elif vnd in self.vnd2vendor:
                unsorted[vnd].append(binding)
            else:
                unknown_vendor_bindings.append(binding)

        # Key functions for sorting.
        def vnd_key(vnd):
            return self.vnd2vendor[vnd].casefold()

        def binding_key(binding):
            return binding.compatible

        # Sort the bindings for each vendor by compatible.
        # Plain dicts are sorted in CPython 3.6+, which is what we
        # support, so the return dict's keys are in the same
        # order as vnd2vendor.
        #
        # The unknown-vendor bindings being inserted as a 1-tuple key is a
        # hack for convenience that ensures they won't collide with a
        # known vendor. The code that consumes the dict below handles
        # this.
        vnd2bindings = {
            None: sorted(generic_bindings, key=binding_key)
        }
        for vnd in sorted(unsorted, key=vnd_key):
            vnd2bindings[vnd] = sorted(unsorted[vnd], key=binding_key)
        vnd2bindings[(UNKNOWN_VENDOR,)] = sorted(unknown_vendor_bindings,
                                                      key=binding_key)

        if logger.isEnabledFor(logging.DEBUG):
            logger.debug('vnd2bindings: %s', pprint.pformat(vnd2bindings))

        return vnd2bindings

    def init_vnd2ref_target(self):
        # The return value, vnd2ref_target, is a dict mapping vendor
        # prefixes to ref targets for their relevant sections in this
        # file, with these special cases:
        #
        # - The None key maps to the ref target for bindings with no
        #   vendor prefix in their compatibles, like 'gpio-keys'
        # - The (UNKNOWN_VENDOR,) key maps to the ref target for bindings
        #   whose compatible has a vendor prefix that is not recognized.
        vnd2ref_target = {}

        for vnd in self.vnd2bindings:
            if vnd is None:
                vnd2ref_target[vnd] = 'dt_no_vendor'
            elif isinstance(vnd, str):
                vnd2ref_target[vnd] = f'dt_vendor_{vnd}'
            else:
                assert vnd == (UNKNOWN_VENDOR,), vnd
                vnd2ref_target[vnd] = 'dt_unknown_vendor'

        return vnd2ref_target

def main():
    args = parse_args()
    setup_logging(args.verbose)
    bindings = load_bindings(args.dts_roots)
    base_binding = load_base_binding()
    vnd_lookup = VndLookup(args.vendor_prefixes, bindings)
    dump_content(bindings, base_binding, vnd_lookup, args.out_dir)

def parse_args():
    # Parse command line arguments from sys.argv.

    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--verbose', default=0, action='count',
                        help='increase verbosity; may be given multiple times')
    parser.add_argument('--vendor-prefixes', required=True,
                        help='vendor-prefixes.txt file path')
    parser.add_argument('--dts-root', dest='dts_roots', action='append',
                        help='''additional DTS root directory as it would
                        be set in DTS_ROOTS''')
    parser.add_argument('out_dir', help='output files are generated here')

    return parser.parse_args()

def setup_logging(verbose):
    if verbose >= 2:
        log_level = logging.DEBUG
    elif verbose == 1:
        log_level = logging.INFO
    else:
        log_level = logging.ERROR
    logging.basicConfig(format='%(filename)s:%(levelname)s: %(message)s',
                        level=log_level)

def load_bindings(dts_roots):
    # Get a list of edtlib.Binding objects from searching 'dts_roots'.

    if not dts_roots:
        sys.exit('no DTS roots; use --dts-root to specify at least one')

    binding_files = []
    for dts_root in dts_roots:
        binding_files.extend(glob.glob(f'{dts_root}/dts/bindings/**/*.yaml'))

    bindings = edtlib.bindings_from_paths(binding_files, ignore_errors=True)

    num_total = len(bindings)

    # Remove bindings from the 'vnd' vendor, which is not a real vendor,
    # but rather a stand-in we use for examples and tests when a real
    # vendor would be inappropriate.
    bindings = [binding for binding in bindings if
                compatible_vnd(binding.compatible) != 'vnd']

    logger.info('found %d bindings (ignored %d) in this dts_roots list: %s',
                len(bindings), num_total - len(bindings), dts_roots)

    return bindings

def load_base_binding():
    # Make a Binding object for base.yaml.
    #
    # This helps separate presentation for properties common to all
    # nodes from node-specific properties.

    base_yaml = ZEPHYR_BASE / 'dts' / 'bindings' / 'base' / 'base.yaml'
    if not base_yaml.is_file():
        sys.exit(f'Expected to find base.yaml at {base_yaml}')
    return edtlib.Binding(os.fspath(base_yaml), {}, require_compatible=False,
                          require_description=False)

def dump_content(bindings, base_binding, vnd_lookup, out_dir):
    # Dump the generated .rst files for a vnd2bindings dict.
    # Files are only written if they are changed. Existing .rst
    # files which would not be written by the 'vnd2bindings'
    # dict are removed.

    out_dir = Path(out_dir)

    setup_bindings_dir(bindings, out_dir)
    write_bindings_rst(vnd_lookup, out_dir)
    write_per_compatible_orphans(bindings, base_binding, vnd_lookup, out_dir)

def setup_bindings_dir(bindings, out_dir):
    # Make a set of all the Path objects we will be creating for
    # out_dir / bindings / {compatible}.rst. Delete all the ones that
    # shouldn't be there. Make sure the bindings output directory
    # exists.

    paths = set()
    bindings_dir = out_dir / 'bindings'
    logger.info('making output subdirectory %s', bindings_dir)
    bindings_dir.mkdir(parents=True, exist_ok=True)

    for binding in bindings:
        paths.add(bindings_dir / binding_filename(binding))

    for path in bindings_dir.iterdir():
        if path not in paths:
            logger.info('removing unexpected file %s', path)
            path.unlink()

def write_bindings_rst(vnd_lookup, out_dir):
    # Write out_dir / bindings.rst, the top level index of bindings.

    string_io = io.StringIO()

    print_block(f'''\
    .. _devicetree_binding_index:

    Bindings index
    ##############

    This page documents the available devicetree bindings.
    See {zref('dt-bindings')} for an introduction to the Zephyr bindings
    file format.

    Vendor index
    ************

    This section contains an index of hardware vendors.
    Click on a vendor's name to go to the list of bindings for
    that vendor.

    .. rst-class:: rst-columns
    ''', string_io)

    for vnd in vnd_lookup.vnd2bindings:
        print(f'- :ref:`{vnd_lookup.target(vnd)}`', file=string_io)

    print_block('''\

    Bindings by vendor
    ******************

    This section contains available bindings, grouped by vendor.
    Within each group, bindings are listed by the "compatible" property
    they apply to, like this:

    **Vendor name (vendor prefix)**

    .. rst-class:: rst-columns

    - <compatible-A>
    - <compatible-B> (on <bus-name> bus)
    - <compatible-C>
    - ...

    The text "(on <bus-name> bus)" appears when bindings may behave
    differently depending on the bus the node appears on.
    For example, this applies to some sensor device nodes, which may
    appear as children of either I2C or SPI bus nodes.
    ''', string_io)

    for vnd, bindings in vnd_lookup.vnd2bindings.items():
        if isinstance(vnd, tuple):
            title = vnd[0]
        else:
            title = vnd_lookup.vendor(vnd).strip()
            if isinstance(vnd, str):
                title += f' ({vnd})'
        underline = '=' * len(title)

        print_block(f'''\
        .. _{vnd_lookup.target(vnd)}:

        {title}
        {underline}

        .. rst-class:: rst-columns
        ''', string_io)
        for binding in bindings:
            print(f'- :ref:`{binding_ref_target(binding)}`', file=string_io)
        print(file=string_io)

    write_if_updated(out_dir / 'bindings.rst', string_io.getvalue())

def write_per_compatible_orphans(bindings, base_binding, vnd_lookup, out_dir):
    # For each compatible in vnd2bindings, write the corresponding
    # out_dir / bindings / {binding.compatible}.rst file, if its
    # content needs updating. This file is an 'orphan' because it's not
    # in any toctree.

    logging.info('updating up to %d :orphan: files', len(bindings))
    num_written = 0
    # Names of properties in base.yaml.
    base_names = set(base_binding.prop2specs.keys())
    for binding in bindings:
        string_io = io.StringIO()

        # :orphan:
        #
        # .. ref_target:
        #
        # Title [(on <bus> bus)]
        # ######################
        if binding.on_bus:
            on_bus_title = f' (on {binding.on_bus} bus)'
        else:
            on_bus_title = ''
        compatible = binding.compatible
        title = f'{compatible}{on_bus_title}'
        underline = '#' * len(title)
        print_block(f'''\
        :orphan:

        .. _{binding_ref_target(binding)}:

        {title}
        {underline}
        ''', string_io)

        # Vendor: <link-to-vendor-section>
        vnd = compatible_vnd(compatible)
        print('Vendor: '
              f':ref:`{vnd_lookup.vendor(vnd)} <{vnd_lookup.target(vnd)}>`\n',
              file=string_io)

        # Binding description.
        if binding.bus:
            bus_help = f'These nodes are "{binding.bus}" bus nodes.'
        else:
            bus_help = ''
        print_block(f'''\
        Description
        ***********

        {bus_help}
        ''', string_io)
        print(to_code_block(binding.description.strip()), file=string_io)

        # Properties.
        print_block('''\
        Properties
        **********
        ''', string_io)
        print_top_level_properties(binding, base_names, string_io)
        print_child_binding_properties(binding, string_io)

        # Specifier cells.
        #
        # This presentation isn't particularly nice. Perhaps something
        # better can be done for future work.
        if binding.specifier2cells:
            print_block('''\
            Specifier cell names
            ********************
            ''', string_io)
            for specifier, cells in binding.specifier2cells.items():
                print(f'- {specifier} cells: {", ".join(cells)}',
                      file=string_io)

        written = write_if_updated(out_dir / 'bindings' /
                                   binding_filename(binding),
                                   string_io.getvalue())

        if written:
            num_written += 1

    logging.info('done writing :orphan: files; %d files needed updates',
                 num_written)

def print_top_level_properties(binding, base_names, string_io):
    # Print the RST for top level properties for 'binding' to 'string_io'.
    #
    # The 'base_names' set contains all the base.yaml properties.

    def prop_table(filter_fn, deprecated):
        # Get a properly formatted and indented table of properties.
        specs = [prop_spec for prop_spec in binding.prop2specs.values()
                 if filter_fn(prop_spec)]
        indent = ' ' * 14
        if specs:
            temp_io = io.StringIO()
            print_property_table(specs, temp_io, deprecated=deprecated)
            return textwrap.indent(temp_io.getvalue(), indent)

        return indent + '(None)'

    def node_props_filter(prop_spec):
        return prop_spec.name not in base_names and not prop_spec.deprecated

    def deprecated_node_props_filter(prop_spec):
        return prop_spec.name not in base_names and prop_spec.deprecated

    def base_props_filter(prop_spec):
        return prop_spec.name in base_names

    if binding.child_binding:
        print_block('''\
        Top level properties
        ====================
        ''', string_io)
    if binding.prop2specs:
        if binding.child_binding:
            print_block(f'''
            These property descriptions apply to "{binding.compatible}"
            nodes themselves. This page also describes child node
            properties in the following sections.
            ''', string_io)


        print_block(f'''\
        .. tabs::

           .. group-tab:: Node specific properties

              Properties not inherited from the base binding file.

{prop_table(node_props_filter, False)}

           .. group-tab:: Deprecated node specific properties

              Deprecated properties not inherited from the base binding file.

{prop_table(deprecated_node_props_filter, False)}

           .. group-tab:: Base properties

              Properties inherited from the base binding file, which defines
              common properties that may be set on many nodes. Not all of these
              may apply to the "{binding.compatible}" compatible.

{prop_table(base_props_filter, True)}

        ''', string_io)
    else:
        print('No top-level properties.\n', file=string_io)

def print_child_binding_properties(binding, string_io):
    # Prints property tables for all levels of nesting of child
    # bindings.

    level = 1
    child = binding.child_binding
    while child is not None:
        if level == 1:
            level_string = 'Child'
        elif level == 2:
            level_string = 'Grandchild'
        else:
            level_string = f'Level {level} child'
        if child.prop2specs:
            title = f'{level_string} node properties'
            underline = '=' * len(title)
            print(f'{title}\n{underline}\n', file=string_io)
            print_property_table(child.prop2specs.values(), string_io,
                                 deprecated=True)
        child = child.child_binding
        level += 1

def print_property_table(prop_specs, string_io, deprecated=False):
    # Writes a table of properties based on 'prop_specs', an iterable
    # of edtlib.PropertySpec objects, to 'string_io'.
    #
    # If 'deprecated' is true and the property is deprecated, an extra
    # line is printed mentioning that fact. We allow this to be turned
    # off for tables where all properties are deprecated, so it's
    # clear from context.

    # Table header.
    print_block('''\
    .. list-table::
       :widths: 1 1 4
       :header-rows: 1

       * - Name
         - Type
         - Details
    ''', string_io)

    def to_prop_table_row(prop_spec):
        # Get a multiline string for a PropertySpec table row.

        # The description column combines the description field,
        # along with things like the default value or enum values.
        #
        # The property 'description' field from the binding may span
        # one or multiple lines. We try to come up with a nice
        # presentation for each.
        details = ''
        raw_prop_descr = prop_spec.description
        if raw_prop_descr:
            details += to_code_block(raw_prop_descr)

        if prop_spec.required:
            details += '\n\nThis property is **required**.'

        if prop_spec.default:
            details += f'\n\nDefault value: ``{prop_spec.default}``'

        if prop_spec.const:
            details += f'\n\nConstant value: ``{prop_spec.const}``'
        elif prop_spec.enum:
            details += ('\n\nLegal values: ' +
                        ', '.join(f'``{repr(val)}``' for val in
                                  prop_spec.enum))

        if prop_spec.name in DETAILS_IN_IMPORTANT_PROPS:
            details += (f'\n\nSee {zref("dt-important-props")} for more '
                        'information.')

        if deprecated and prop_spec.deprecated:
            details += '\n\nThis property is **deprecated**.'

        return f"""\
   * - ``{prop_spec.name}``
     - ``{prop_spec.type}``
     - {textwrap.indent(details, ' ' * 7).lstrip()}
"""

    # Print each row.
    for prop_spec in prop_specs:
        print(to_prop_table_row(prop_spec), file=string_io)

def print_block(block, string_io):
    # Helper for dedenting and printing a triple-quoted RST block.
    # (Just a block of text, not necessarily just a 'code-block'
    # directive.)

    print(textwrap.dedent(block), file=string_io)

def to_code_block(s, indent=0):
    # Converts 's', a string, to an indented rst .. code-block::. The
    # 'indent' argument is a leading indent for each line in the code
    # block, in spaces.
    indent = indent * ' '
    return ('.. code-block:: none\n\n' +
            textwrap.indent(s, indent + '   ') + '\n')

def compatible_vnd(compatible):
    # Get the vendor prefix for a compatible string 'compatible'.
    #
    # For example, compatible_vnd('foo,device') is 'foo'.
    #
    # If 'compatible' has no comma (','), None is returned.

    if ',' not in compatible:
        return None

    return compatible.split(',', 1)[0]

def binding_ref_target(binding):
    # Return the sphinx ':ref:' target name for a binding.

    ret = re.sub('[,-]', '_', binding.compatible)
    if binding.on_bus is not None:
        ret += f'_{binding.on_bus}'
    return ret

def zref(target, text=None):
    # Make an appropriate RST :ref:`text <target>` or :ref:`target`
    # string to a zephyr documentation ref target 'target', and return
    # it.
    #
    # By default, the bindings docs are in the main Zephyr
    # documentation, but this script supports putting them in a
    # separate Sphinx doc set. Since we also link to Zephyr
    # documentation from the generated content, we have an environment
    # variable based escape hatch for putting the target in the zephyr
    # doc set.
    #
    # This relies on intersphinx:
    # https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html

    docset = os.environ.get('GEN_DEVICETREE_REST_ZEPHYR_DOCSET', '')

    if docset.strip():
        target = f'{docset}:{target}'

    if text:
        return f':ref:`{text} <{target}>`'

    return f':ref:`{target}`'

def binding_filename(binding):
    if binding.on_bus is None:
        return f'{binding.compatible}.rst'

    return f'{binding.compatible}-{binding.on_bus}.rst'

def write_if_updated(path, s):
    # gen_helpers.write_if_updated() wrapper that handles logging.

    written = gen_helpers.write_if_updated(path, s)
    logger.debug('%s %s', 'wrote' if written else 'did NOT write', path)
    return written


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