# Path: pyphysim/simulations/configobjvalidation.py
# def real_numpy_array_check(value: Union[str, List[str]],
#                            min: Optional[float] = None,
#                            max: Optional[float] = None) -> List[float]:
#     """
#     Parse and validate `value` as a numpy array (of floats).
# 
#     Value can be either a single number, a range expression in the form of
#     min:max or min:step:max, or even a list containing numbers and range
#     expressions.
# 
#     Parameters
#     ----------
#     value : str, List[str]
#         The string to be converted (of a list of strings to ve converted). This
#         can be either a single number, a range expression in the form of min:max
#          or min:step:max, or even a list containing numbers and range
#          expressions.
#     min : float
#         The minimum allowed value. If the converted value is (or have)
#         lower than `min` then the VdtValueTooSmallError exception will be
#         raised.
#     max : float
#         The maximum allowed value. If the converted value is (or have)
#         greater than `man` then the VdtValueTooSmallError exception will be
#         raised.
# 
#     Returns
#     -------
#     List[float]
#         The parsed numpy array.
# 
#     Notes
#     -----
#     You can either separate the values with commas or spaces (any comma
#     will have the same effect as a space). However, if you separate with
#     spaces the values should be in brackets, while if you separate with
#     commands there should be no brackets.
# 
#     >> SNR = 0,5,10:20
#     >> SNR = [0 5 10:20]
#     """
#     if isinstance(value, str):
#         # Remove '[' and ']' if they exist.
#         if value[0] == '[' and value[-1] == ']':
#             value = value[1:-1].strip()
#             value = value.replace(',', ' ')  # Replace commas with spaces
#             value = value.split()  # Split based on spaces
#             # Notice that at this point value is a list of strings
# 
#     # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
#     # Test if it is a list or not
#     if isinstance(value, list):
#         # If it is a list, each element can be either a number of a 'range
#         # expression' that can be parsed with _parse_float_range_expr. We
#         # simple apply real_numpy_array_check on each element in the list
#         # to do the work and stack horizontally all the results.
#         out = np.hstack([real_numpy_array_check(a, min, max) for a in value])
# 
#     else:
#         # It its not a list, it can be either a single number of a 'range
#         # expression' that can be parsed with _parse_float_range_expr
#         try:
#             out = np.array([validate.is_float(value)])
#         except validate.VdtTypeError:
#             out = _parse_float_range_expr(value)
# 
#     # xxxxxxxxxx Validate if minimum and maximum allowed values xxxxxxxxxxx
#     if min is not None:
#         # maybe "min" was passed as a string and thus we need to convert it
#         # to a float
#         min = float(min)
#         if out.min() < min:
#             raise validate.VdtValueTooSmallError(out.min())
# 
#     if max is not None:
#         # maybe "min" was passed as a string and thus we need to convert it
#         # to a float
#         max = float(max)
#         if out.max() > max:
#             raise validate.VdtValueTooBigError(out.max())
#     # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 
#     return cast(List[float], out.tolist())


from configobj import ConfigObj, flatten_errors
from validate import Validator
from pyphysim.simulations.configobjvalidation import real_numpy_array_check


if __name__ == '__main__':
    config_file_name = 'psk_simulation_config.txt'

    # Spec could be also the name of a file containing the string below
    spec = """[Scenario]
    SNR=real_numpy_array(default=15)
    modulator=option('PSK', 'QAM', 'BPSK', default="PSK")
    M=integer(min=4, max=512, default=4)
    NSymbs=integer(min=10, max=1000000, default=200)
    K=integer(min=2,default=3)
    Nr=integer(min=2,default=2)
    Nt=integer(min=2,default=2)
    Ns=integer(min=1,default=1)
    [IA Algorithm]
    max_iterations=integer(min=1, default=60)
    [General]
    rep_max=integer(min=1, default=2000)
    max_bit_errors=integer(min=1, default=3000)
    unpacked_parameters=string_list(default=list('SNR'))
    """.split("\n")

    conf_file_parser = ConfigObj(config_file_name,
                                 list_values=True,
                                 configspec=spec)

    #conf_file_parser.write()

    # Dictionary with custom validation functions

# Path: pyphysim/simulations/configobjvalidation.py
# def real_numpy_array_check(value: Union[str, List[str]],
#                            min: Optional[float] = None,
#                            max: Optional[float] = None) -> List[float]:
#     """
#     Parse and validate `value` as a numpy array (of floats).
# 
#     Value can be either a single number, a range expression in the form of
#     min:max or min:step:max, or even a list containing numbers and range
#     expressions.
# 
#     Parameters
#     ----------
#     value : str, List[str]
#         The string to be converted (of a list of strings to ve converted). This
#         can be either a single number, a range expression in the form of min:max
#          or min:step:max, or even a list containing numbers and range
#          expressions.
#     min : float
#         The minimum allowed value. If the converted value is (or have)
#         lower than `min` then the VdtValueTooSmallError exception will be
#         raised.
#     max : float
#         The maximum allowed value. If the converted value is (or have)
#         greater than `man` then the VdtValueTooSmallError exception will be
#         raised.
# 
#     Returns
#     -------
#     List[float]
#         The parsed numpy array.
# 
#     Notes
#     -----
#     You can either separate the values with commas or spaces (any comma
#     will have the same effect as a space). However, if you separate with
#     spaces the values should be in brackets, while if you separate with
#     commands there should be no brackets.
# 
#     >> SNR = 0,5,10:20
#     >> SNR = [0 5 10:20]
#     """
#     if isinstance(value, str):
#         # Remove '[' and ']' if they exist.
#         if value[0] == '[' and value[-1] == ']':
#             value = value[1:-1].strip()
#             value = value.replace(',', ' ')  # Replace commas with spaces
#             value = value.split()  # Split based on spaces
#             # Notice that at this point value is a list of strings
# 
#     # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
#     # Test if it is a list or not
#     if isinstance(value, list):
#         # If it is a list, each element can be either a number of a 'range
#         # expression' that can be parsed with _parse_float_range_expr. We
#         # simple apply real_numpy_array_check on each element in the list
#         # to do the work and stack horizontally all the results.
#         out = np.hstack([real_numpy_array_check(a, min, max) for a in value])
# 
#     else:
#         # It its not a list, it can be either a single number of a 'range
#         # expression' that can be parsed with _parse_float_range_expr
#         try:
#             out = np.array([validate.is_float(value)])
#         except validate.VdtTypeError:
#             out = _parse_float_range_expr(value)
# 
#     # xxxxxxxxxx Validate if minimum and maximum allowed values xxxxxxxxxxx
#     if min is not None:
#         # maybe "min" was passed as a string and thus we need to convert it
#         # to a float
#         min = float(min)
#         if out.min() < min:
#             raise validate.VdtValueTooSmallError(out.min())
# 
#     if max is not None:
#         # maybe "min" was passed as a string and thus we need to convert it
#         # to a float
#         max = float(max)
#         if out.max() > max:
#             raise validate.VdtValueTooBigError(out.max())
#     # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 
#     return cast(List[float], out.tolist())


# Path: apps/configobj_usage_example.py
from configobj import ConfigObj, flatten_errors
from validate import Validator
from pyphysim.simulations.configobjvalidation import real_numpy_array_check



if __name__ == '__main__':
    config_file_name = 'psk_simulation_config.txt'

    # Spec could be also the name of a file containing the string below
    spec = """[Scenario]
    SNR=real_numpy_array(default=15)
    modulator=option('PSK', 'QAM', 'BPSK', default="PSK")
    M=integer(min=4, max=512, default=4)
    NSymbs=integer(min=10, max=1000000, default=200)
    K=integer(min=2,default=3)
    Nr=integer(min=2,default=2)
    Nt=integer(min=2,default=2)
    Ns=integer(min=1,default=1)
    [IA Algorithm]
    max_iterations=integer(min=1, default=60)
    [General]
    rep_max=integer(min=1, default=2000)
    max_bit_errors=integer(min=1, default=3000)
    unpacked_parameters=string_list(default=list('SNR'))
    """.split("\n")

    conf_file_parser = ConfigObj(config_file_name,
                                 list_values=True,
                                 configspec=spec)

    #conf_file_parser.write()

    # Dictionary with custom validation functions

    fdict = {'real_numpy_array': real_numpy_array_check}