# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

from typing import Dict, Optional
from .clocks import Clocks


class ResetItem:
    '''Individual resets'''
    def __init__(self, hier: Dict[str, str], raw: Dict[str, object], clocks: Clocks):
        if not raw['name']:
            raise ValueError('Reset has no name')

        self.name = raw['name']
        self.gen = raw.get('gen', True)
        self.rst_type = raw.get('type', 'top')

        self.path = ""
        if self.rst_type == 'top':
            self.path = f"{hier['top']}rst_{self.name}_n"
            self.lpg_path = f"{hier['lpg']}{self.name}"
        elif self.rst_type == 'ext':
            self.path = f"{hier['ext']}{self.name}"

        self.shadow_path = ""
        if self.rst_type == 'top':
            self.shadow_path = f"{hier['top']}rst_{self.name}_shadowed_n"
            self.shadow_lpg_path = f"{hier['lpg']}{self.name}_shadowed"

        # to be constructed later
        self.domains = []
        self.shadowed = False

        self.parent = raw.get('parent', "")

        # This can be a source clock or a derived source
        if self.rst_type != 'ext':
            self.clock = clocks.get_clock_by_name(raw['clk'])
        else:
            self.clock = None

        self.sw = bool(raw.get('sw', 0))

    def _asdict(self) -> Dict[str, object]:
        ret = {
            'name': self.name,
            'gen': self.gen,
            'type': self.rst_type,
            'domains': self.domains,
            'shadowed': self.shadowed,
            'sw': self.sw,
            'path': self.path
        }

        if self.parent:
            ret['parent'] = self.parent

        if self.clock:
            ret['clock'] = self.clock.name

        return ret


class Resets:
    '''Resets for the chip'''
    def __init__(self, raw: Dict[str, object], clocks: Clocks):
        self.hier_paths = {}
        assert isinstance(raw['hier_paths'], dict)
        for rst_src, path in raw['hier_paths'].items():
            self.hier_paths[str(rst_src)] = str(path)

        assert isinstance(raw['nodes'], list)

        self.nodes = {}
        for node in raw['nodes']:
            assert isinstance(node, dict)
            reset = ResetItem(self.hier_paths, node, clocks)
            self.nodes[reset.name] = reset

    def _asdict(self) -> Dict[str, object]:
        ret = {
            'hier_paths': self.hier_paths,
            'nodes': list(self.nodes.values())
        }

        return ret

    def get_reset_by_name(self, name: str) -> ResetItem:

        ret = self.nodes.get(name, None)
        if ret:
            return ret
        else:
            raise ValueError(f'{name} is not a defined reset')

    def mark_reset_shadowed(self, name: str):
        '''Mark particular reset as requiring shadow'''

        reset = self.get_reset_by_name(name)
        reset.shadowed = True

    def get_reset_domains(self, name: str):
        '''Get available domains for a reset'''

        return self.get_reset_by_name(name).domains

    def get_clocks(self) -> list:
        '''Get associated clocks'''

        clocks = {}
        for reset in self.nodes.values():
            if reset.rst_type != 'ext':
                clocks[reset.clock.name] = 1

        return list(clocks)

    def get_generated_resets(self) -> list:
        '''Get generated resets and return reset object
        '''
        return [reset
                for reset in self.nodes.values()
                if reset.gen]

    def get_top_resets(self) -> list:
        '''Get resets pushed to the top level'''

        return [reset
                for reset in self.nodes.values()
                if reset.rst_type == 'top']

    def get_sw_resets(self) -> list:
        '''Get software controlled resets'''

        return [reset.name
                for reset in self.nodes.values()
                if reset.sw]

    def get_path(self, name: str, domain: Optional[str], shadow = False) -> str:
        '''Get path to reset'''

        reset = self.get_reset_by_name(name)
        if reset.rst_type == 'int':
            raise ValueError(f'Reset {name} is not a reset exported from rstmgr')

        if reset.rst_type == 'ext':
            return reset.path

        if shadow:
            path = reset.shadow_path
        else:
            path = reset.path

        if domain:
            path += f'[rstmgr_pkg::Domain{domain}Sel]'

        return path

    def get_lpg_path(self, name: str, domain: Optional[str], shadow = False) -> str:
        '''Get path to lpg indication signals'''

        reset = self.get_reset_by_name(name)
        if reset.rst_type == 'int':
            raise ValueError(f'Reset {name} is not a reset exported from rstmgr')

        if reset.rst_type == 'ext':
            raise ValueError(f'External reset {name} cannot be associated with an LPG')

        if shadow:
            path = reset.shadow_lpg_path
        else:
            path = reset.lpg_path

        if domain:
            path += f'[rstmgr_pkg::Domain{domain}Sel]'

        return path

    def get_unused_resets(self, domains: list) -> Dict[str, str]:
        '''Get unused resets'''

        top_resets = [reset
                      for reset in self.nodes.values()
                      if reset.rst_type == 'top']

        ret = {}
        for reset in top_resets:
            for dom in domains:
                if dom not in reset.domains:
                    ret[f'rst_{reset.name}_n[{domains.index(dom)}]'] = \
                        f'{reset.path}[rstmgr_pkg::Domain{dom}Sel]'

                    if reset.shadowed:
                        ret[f'rst_{reset.name}_shadowed_n[{domains.index(dom)}]'] = \
                            f'{reset.shadow_path}[rstmgr_pkg::Domain{dom}Sel]'

        return ret

    def add_reset_domain(self, name: str, domain: str):
        '''Mark particular reset as requiring shadow'''

        reset = self.get_reset_by_name(name)

        # Other reset types of hardwired domains
        if reset.rst_type == 'top':
            if domain not in reset.domains:
                reset.domains.append(domain)

    def has_shadowed_reset(self) -> bool:
        '''Do any generated resets have a shadow version?'''

        for reset in self.nodes.values():
            if reset.shadowed:
                return True

        return False
