import random


def create_segmented_signals(signal, annmap, sample_rate=257, sec=2):
    """
    Creates segmented signals containing all possible anomalies from a signal and its annmap

    :param signal: the signal to segment
    :param annmap: map containing the positions of the annotations
    :param sample_rate: the sample rate of the signal
    :param sec: length of the segments
    :return: a list of dictionaries containing the segments and metadata
    """
    seg_len = sec * sample_rate
    segments = []

    curr_ini = curr_fin = 0

    for i, sample in enumerate(annmap):
        if sample['ann'] == 'N':
            if curr_ini == 0:
                if i + 1 < len(annmap) - 1 and annmap[i + 1]['ann'] == 'N':
                    curr_ini = random.randint(sample['time'], annmap[i + 1]['time'])
                else:
                    continue
            curr_fin = sample['time']

            if curr_fin - curr_ini > seg_len and curr_ini + seg_len <= signal.shape[0]:
                segments.append(
                    {
                        'data': signal[curr_ini:curr_ini + seg_len, :],
                        'ann': 'N'
                    }
                )
                curr_ini = curr_fin
        else:
            curr_ini = curr_fin = 0
            if sample['time'] > 2 * seg_len and sample['time'] < signal.shape[0] - 2 * seg_len:
                rand_start = sample['time'] - random.randint(seg_len // 3, 2 * seg_len // 3)
                segments.append(
                    {
                        'data': signal[rand_start:rand_start + seg_len, :],
                        'ann': sample['ann'],
                        'time': sample['time']
                    }
                )

    return segments