#
# Copyright (c) 2018 Bobby Noelte
#
# SPDX-License-Identifier: Apache-2.0
#

from extract.globals import *
from extract.directive import DTDirective

##
# @brief Manage clocks related directives.
#
# Handles:
# - clocks
# directives.
#
class DTClocks(DTDirective):
    def _extract_consumer(self, node_path, clocks, def_label):

        clock_consumer = reduced[node_path]
        clock_consumer_bindings = get_binding(node_path)
        clock_consumer_label = 'DT_' + node_label(node_path)

        clock_index = 0
        clock_cell_index = 0
        nr_clock_cells = 0
        clock_provider_node_path = ''
        clock_provider = {}
        for cell in clocks:
            if clock_cell_index == 0:
                if cell not in phandles:
                    raise Exception(
                        ("Could not find the clock provider node {} for clocks"
                         " = {} in clock consumer node {}. Did you activate"
                         " the clock node?. Last clock provider: {}.")
                            .format(str(cell), str(clocks), node_path,
                                    str(clock_provider)))
                clock_provider_node_path = phandles[cell]
                clock_provider = reduced[clock_provider_node_path]
                clock_provider_bindings = get_binding(
                                            clock_provider_node_path)
                clock_provider_label = node_label(clock_provider_node_path)
                nr_clock_cells = int(clock_provider['props'].get(
                                     '#clock-cells', 0))
                clock_cells_string = clock_provider_bindings.get(
                    'cell_string', 'CLOCK')
                clock_cells_names = clock_provider_bindings.get(
                    '#cells', ['ID', 'CELL1',  "CELL2", "CELL3"])
                clock_cells = []
            else:
                clock_cells.append(cell)
            clock_cell_index += 1
            if clock_cell_index > nr_clock_cells:
                # clock consumer device - clocks info
                #####################################
                prop_def = {}
                prop_alias = {}

                # Legacy clocks definitions by extract_cells
                for i, cell in enumerate(clock_cells):
                    if i >= len(clock_cells_names):
                        clock_cell_name = 'CELL{}'.format(i)
                    else:
                        clock_cell_name = clock_cells_names[i]
                    if clock_cells_string == clock_cell_name:
                        clock_label = self.get_label_string([
                            clock_consumer_label, clock_cells_string,
                            str(clock_index)])
                        add_compat_alias(node_path,
                                self.get_label_string(["",
                                    clock_cells_string, str(clock_index)]),
                                clock_label, prop_alias)
                    else:
                        clock_label = self.get_label_string([
                            clock_consumer_label, clock_cells_string,
                            clock_cell_name, str(clock_index)])
                        add_compat_alias(node_path,
                                self.get_label_string(["",
                                    clock_cells_string, clock_cell_name,
                                    str(clock_index)]),
                                clock_label, prop_alias)
                    prop_def[clock_label] = str(cell)
                    if clock_index == 0 and \
                        len(clocks) == (len(clock_cells) + 1):
                        index = ''
                    else:
                        index = str(clock_index)
                    if node_path in aliases:
                        if clock_cells_string == clock_cell_name:
                            add_prop_aliases(
                                node_path,
                                lambda alias:
                                    self.get_label_string([
                                        alias,
                                        clock_cells_string,
                                        index]),
                                clock_label,
                                prop_alias)
                        else:
                            add_prop_aliases(
                                node_path,
                                lambda alias:
                                    self.get_label_string([
                                        alias,
                                        clock_cells_string,
                                        clock_cell_name,
                                        index]),
                                clock_label,
                                prop_alias)
                    # alias
                    if i < nr_clock_cells:
                        # clocks info for first clock
                        clock_alias_label = self.get_label_string([
                            clock_consumer_label, clock_cells_string,
                            clock_cell_name])
                        prop_alias[clock_alias_label] = clock_label
                        add_compat_alias(node_path,
                                self.get_label_string(["",
                                    clock_cells_string, clock_cell_name]),
                                clock_label, prop_alias)


                # Legacy clocks definitions by extract_controller
                clock_provider_label_str = clock_provider['props'].get('label',
                                                                       None)
                if clock_provider_label_str is not None:
                    try:
                        generation = clock_consumer_bindings['properties'][
                            'clocks']['generation']
                    except:
                        generation = ''
                    if 'use-prop-name' in generation:
                        clock_cell_name = 'CLOCKS_CONTROLLER'
                    else:
                        clock_cell_name = 'CLOCK_CONTROLLER'
                    if clock_index == 0 and \
                        len(clocks) == (len(clock_cells) + 1):
                        index = ''
                    else:
                        index = str(clock_index)
                    clock_label = self.get_label_string([clock_consumer_label,
                                                         clock_cell_name,
                                                         index])
                    add_compat_alias(node_path,
                            self.get_label_string(["", clock_cell_name, index]),
                            clock_label, prop_alias)
                    prop_def[clock_label] = '"' + clock_provider_label_str + '"'
                    if node_path in aliases:
                        add_prop_aliases(
                            node_path,
                            lambda alias:
                                self.get_label_string([
                                    alias,
                                    clock_cell_name,
                                    index]),
                            clock_label,
                            prop_alias)

                insert_defs(node_path, prop_def, prop_alias)

                clock_cell_index = 0
                clock_index += 1

    ##
    # @brief Extract clocks related directives
    #
    # @param node_path Path to node owning the clockxxx definition.
    # @param prop clockxxx property name
    # @param def_label Define label string of node owning the directive.
    #
    def extract(self, node_path, prop, def_label):

        properties = reduced[node_path]['props'][prop]

        prop_list = []
        if not isinstance(properties, list):
            prop_list.append(properties)
        else:
            prop_list = list(properties)

        if prop == 'clocks':
            # indicator for clock consumers
            self._extract_consumer(node_path, prop_list, def_label)
        else:
            raise Exception(
                "DTClocks.extract called with unexpected directive ({})."
                    .format(prop))

##
# @brief Management information for clocks.
clocks = DTClocks()
