from typing import Dict, List, cast

from py_headless_daw.project.parameter import Parameter, ParameterValueType, ParameterRangeType


class HavingParameters:

    def __init__(self):
        self._parameters: Dict[str, Parameter] = {}
        super().__init__()

    def has_parameter(self, name: str) -> bool:
        return name in self._parameters

    def add_parameter(self,
                      name: str,
                      value: ParameterValueType,
                      param_type: str,
                      value_range: ParameterRangeType):

        if name in self._parameters:
            raise Exception('parameter named ' + name + ' already added to this object')

        parameter = Parameter(name, value, param_type, value_range)
        self._parameters[name] = parameter

    def add_parameter_object(self, parameter: Parameter) -> None:
        self._parameters[parameter.name] = parameter

    def get_parameter(self, name: str) -> Parameter:
        for parameter in self.parameters:
            if parameter.name == name:
                return parameter

        list_of_names: List[str] = [p.name for p in self.parameters]

        # noinspection PyTypeChecker
        available_names: List[str] = cast(List[str], list_of_names)

        raise Exception('parameter named ' + name + ' not found. Available: ' + ', '.join(available_names))

    def get_parameter_value(self, name: str) -> ParameterValueType:
        param = self.get_parameter(name)
        return param.value

    def get_float_parameter_value(self, name: str) -> float:
        param = self.get_parameter(name)
        if param.type != Parameter.TYPE_FLOAT:
            raise ValueError(f"parameter {name} was expected to be float (error: f009d0ef)")
        value = self.get_parameter_value(name)
        cast_value = cast(float, value)
        return cast_value

    def get_enum_parameter_value(self, name: str) -> str:
        param = self.get_parameter(name)
        if param.type != Parameter.TYPE_ENUM:
            raise ValueError(f"parameter {name} was expected to be enum (error: 80a1d180)")
        value = self.get_parameter_value(name)
        cast_value = cast(str, value)
        return cast_value

    def set_parameter_value(self, name: str, value: ParameterValueType):
        param = self.get_parameter(name)
        param.value = value

    @property
    def parameters(self) -> List[Parameter]:
        return list(self._parameters.values())

[((24, 20, 24, 67), 'py_headless_daw.project.parameter.Parameter', 'Parameter', ({(24, 30, 24, 34): 'name', (24, 36, 24, 41): 'value', (24, 43, 24, 53): 'param_type', (24, 55, 24, 66): 'value_range'}, {}), '(name, value, param_type, value_range)', False, 'from py_headless_daw.project.parameter import Parameter, ParameterValueType, ParameterRangeType\n'), ((38, 37, 38, 67), 'typing.cast', 'cast', ({(38, 42, 38, 51): 'List[str]', (38, 53, 38, 66): 'list_of_names'}, {}), '(List[str], list_of_names)', False, 'from typing import Dict, List, cast\n'), ((51, 21, 51, 39), 'typing.cast', 'cast', ({(51, 26, 51, 31): 'float', (51, 33, 51, 38): 'value'}, {}), '(float, value)', False, 'from typing import Dict, List, cast\n'), ((59, 21, 59, 37), 'typing.cast', 'cast', ({(59, 26, 59, 29): 'str', (59, 31, 59, 36): 'value'}, {}), '(str, value)', False, 'from typing import Dict, List, cast\n')]