# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
"""Enumerated types for fields
Generated by validation, used by backends
"""

from enum import Enum

from .lib import check_str


class JsonEnum(Enum):
    def for_json(x) -> str:
        return str(x)


class SwWrAccess(JsonEnum):
    WR = 1
    NONE = 2


class SwRdAccess(JsonEnum):
    RD = 1
    RC = 2  # Special handling for port
    NONE = 3


class SwAccess(JsonEnum):
    RO = 1
    RW = 2
    WO = 3
    W1C = 4
    W1S = 5
    W0C = 6
    RC = 7
    R0W1C = 8
    NONE = 9


class HwAccess(JsonEnum):
    HRO = 1
    HRW = 2
    HWO = 3
    NONE = 4  # No access allowed


# swaccess permitted values
# text description, access enum, wr access enum, rd access enum, ok in window
SWACCESS_PERMITTED = {
    'none':  ("No access",                                              # noqa: E241
              SwAccess.NONE, SwWrAccess.NONE, SwRdAccess.NONE, False),  # noqa: E241
    'ro':    ("Read Only",                                              # noqa: E241
              SwAccess.RO,   SwWrAccess.NONE, SwRdAccess.RD,   True),   # noqa: E241
    'rc':    ("Read Only, reading clears",                              # noqa: E241
              SwAccess.RC,   SwWrAccess.WR,   SwRdAccess.RC,   False),  # noqa: E241
    'rw':    ("Read/Write",                                             # noqa: E241
              SwAccess.RW,   SwWrAccess.WR,   SwRdAccess.RD,   True),   # noqa: E241
    'r0w1c': ("Read zero, Write with 1 clears",                         # noqa: E241
              SwAccess.W1C,  SwWrAccess.WR,   SwRdAccess.NONE, False),  # noqa: E241
    'rw1s':  ("Read, Write with 1 sets",                                # noqa: E241
              SwAccess.W1S,  SwWrAccess.WR,   SwRdAccess.RD,   False),  # noqa: E241
    'rw1c':  ("Read, Write with 1 clears",                              # noqa: E241
              SwAccess.W1C,  SwWrAccess.WR,   SwRdAccess.RD,   False),  # noqa: E241
    'rw0c':  ("Read, Write with 0 clears",                              # noqa: E241
              SwAccess.W0C,  SwWrAccess.WR,   SwRdAccess.RD,   False),  # noqa: E241
    'wo':    ("Write Only",                                             # noqa: E241
              SwAccess.WO,   SwWrAccess.WR,   SwRdAccess.NONE, True)    # noqa: E241
}

# hwaccess permitted values
HWACCESS_PERMITTED = {
    'hro': ("Read Only", HwAccess.HRO),
    'hrw': ("Read/Write", HwAccess.HRW),
    'hwo': ("Write Only", HwAccess.HWO),
    'none': ("No Access Needed", HwAccess.NONE)
}


class SWAccess:
    def __init__(self, where: str, raw: object):
        self.key = check_str(raw, 'swaccess for {}'.format(where))
        try:
            self.value = SWACCESS_PERMITTED[self.key]
        except KeyError:
            raise ValueError('Unknown swaccess key, {}, for {}.'
                             .format(self.key, where)) from None

    def dv_rights(self) -> str:
        if self.key in ['none', 'ro', 'rc']:
            return "RO"
        elif self.key in ['rw', 'r0w1c', 'rw1s', 'rw1c', 'rw0c']:
            return "RW"
        else:
            assert self.key == 'wo'
            return "WO"

    def swrd(self) -> SwRdAccess:
        return self.value[3]

    def allows_read(self) -> bool:
        return self.value[3] != SwRdAccess.NONE

    def allows_write(self) -> bool:
        return self.value[2] == SwWrAccess.WR


class HWAccess:
    def __init__(self, where: str, raw: object):
        self.key = check_str(raw, 'hwaccess for {}'.format(where))
        try:
            self.value = HWACCESS_PERMITTED[self.key]
        except KeyError:
            raise ValueError('Unknown hwaccess key, {}, for {}.'
                             .format(self.key, where)) from None

    def allows_read(self) -> bool:
        return self.key in ['hro', 'hrw']

    def allows_write(self) -> bool:
        return self.key in ['hrw', 'hwo']
