# Copyright (c) 2015 Riverbed Technology, Inc.
#
# This software is licensed under the terms and conditions of the MIT License
# accompanying the software ("License").  This software is distributed "AS IS"
# as set forth in the License.

"""This file defines a very basic wave generator."""

import math


class Wave(object):

    def __init__(self, period, alpha, beta, func):
        """Define a waveform

        :param int period:  wave period in secs
        :param float alpha: amplitude
        :param float beta:  offset
        :param str func:    base function - sin or cos

        """
        self.period = period
        self.alpha = alpha
        self.beta = beta

        funcmap = {
            'sin': math.sin,
            'cos': math.cos,
            }
        if func not in funcmap:
            raise Exception('Unknown function: %s' % func)

        self.func = funcmap[func]

    def compute(self, t):
        '''Compute the waveform at time t'''

        rad = (t / self.period) * 2 * math.pi
        return (self.alpha * self.func(rad)) + self.beta


class WaveGenerator(object):

    def generate(self, t0, t1, waves, resolution=1, progress=None):
        """Generate a set of waves.

        :param int t0: start time in epoch seconds
        :param int t1: end time in epoch seconds
        :param int resolution: distance between points in seconds
        :param list waves: list of Wave objects to generate
        :param func progress: optional function to call to update progress

        :returns: list of lists of data values

        This function computes a series of wave forms and returns
        a list of rows.  Each row is comprised of the timestamp (epoch
        seconds) followed by one floating point value for each
        wave.

        """

        rows = []

        t = t0
        while t < t1:
            row = []
            row.append(t)

            for wave in waves:
                row.append(wave.compute(t))

            rows.append(row)
            t = t + resolution

            if progress:
                progress(100*(float(t)-float(t0))/(float(t1)-(t0)))

        return rows
