"""Defines methods for generating synthetic data with varying levels of realism."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/10_synthetic_data.ipynb.

# %% auto 0
__all__ = ['generate_activity_from_light']

# %% ../nbs/api/10_synthetic_data.ipynb 4
import matplotlib.pyplot as plt
import numpy as np
from .lights import LightSchedule

# %% ../nbs/api/10_synthetic_data.ipynb 5
def generate_activity_from_light(
    time: np.ndarray, # time points.
    light: LightSchedule, # light schedule.
    mu_l: float=5.0, # mean of low activity levels.
    mu_h: float=25.0, # mean of high activity levels.
    mu_s: float=0.0, # mean of sleep activity levels.
    sigma_l: float=7.5, # std of low activity levels.
    sigma_h: float=30.0, # std of high activity levels.
    sigma_s: float=2.0, # std of activity during sleep.
    active_level: float=0.5, # person's activity level from 0 to 1. Represents the probability of choosing from the high or low activity distributions at any point in time. Values close to 1 increase the proportion of high activity values.
) -> np.ndarray:
    "Generates an 'activity' schedule from an input light schedule. The activity schedule produced is a corrupted version of the light schedule."
    # input validation
    if not isinstance(mu_l, (float, int)):
        raise TypeError(f"mu_l must be a float or int, got {type(mu_l)}")
    elif mu_l < 0.0:
        raise ValueError(f"mu_l must be a nonnegative float or int, got {mu_l}")
    if not isinstance(mu_h, (float, int)):
        raise TypeError(f"mu_h must be a float or int, got {type(mu_h)}")
    elif mu_h < 0.0:
        raise ValueError(f"mu_h must be a nonnegative float or int, got {mu_h}")
    if not isinstance(mu_s, (float, int)):
        raise TypeError(f"mu_s must be a float or int, got {type(mu_s)}")
    elif mu_s < 0.0:
        raise ValueError(f"mu_s must be a nonnegative float or int, got {mu_s}")
    if not isinstance(sigma_l, (float, int)):
        raise TypeError(f"sigma_l must be a float or int, got {type(sigma_l)}")
    elif sigma_l < 0.0:
        raise ValueError(f"sigma_l must be a nonnegative float or int, got {sigma_l}")
    if not isinstance(sigma_h, (float, int)):
        raise TypeError(f"sigma_h must be a float or int, got {type(sigma_h)}")
    elif sigma_h < 0.0:
        raise ValueError(f"sigma_h must be a nonnegative float or int, got {sigma_h}")
    if not isinstance(sigma_s, (float, int)):
        raise TypeError(f"sigma_s must be a float or int, got {type(sigma_s)}")
    elif sigma_s < 0.0:
        raise ValueError(f"sigma_s must be a nonnegative float or int, got {sigma_s}")
    if not isinstance(active_level, (float, int)):
        raise TypeError(f"active_level must be a float or int, got {type(active_level)}")
    elif active_level < 0.0 or active_level > 1.0:
        raise ValueError(f"active_level must be between 0.0 and 1.0, got {active_level}")
    # check that time is a Numpy array
    if not isinstance(time, np.ndarray):
        raise TypeError("`time` must be a Numpy array")
    # check that the light schedule is a LightSchedule
    if not isinstance(light, LightSchedule):
        raise TypeError("`light` must be a `LightSchedule` object")

    # create the activity vector the same size as time
    activity = np.zeros(time.shape)
    for t in range(time.shape[0]):
        if light(time[t]) == 0:
            activity[t] = np.abs(np.random.normal(mu_s, sigma_s))
        elif light(time[t]) > 0:
            high_activity = np.random.uniform() <= active_level
            if high_activity == True:
                activity[t] = np.abs(np.random.normal(mu_h, sigma_h))
            elif high_activity == False:
                activity[t] = np.abs(np.random.normal(mu_l, sigma_l))
    return activity
