import numpy as np


class BSTDP:
    def __init__(
        self, synapse,
        A_pos=1.0,
        A_neg=1.0,
        tau_pos=3.0,
        tau_neg=3.0,
        learning_rate=0.01,
        upper_limit=1.0,
        lower_limit=0.0):
        self.A_pos = A_pos
        self.A_neg = A_neg
        self.tau_pos = tau_pos
        self.tau_neg = tau_neg
        self.learning_rate = learning_rate
        self.synapse = synapse
        self.upper_limit = upper_limit
        self.lower_limit = lower_limit

    def __call__(self):
        dt = self.synapse.last_bp - self.synapse.last_stimuli_input
        if dt >= 0:
            dw = self.A_pos * np.exp(-dt / self.tau_pos) * self.synapse.weight
            limiter = self.upper_limit - self.synapse.weight
            self.synapse.weight += self.learning_rate * dw * limiter
        elif dt < 0:
            dw = self.A_neg * np.exp(dt / self.tau_neg) * self.synapse.weight
            limiter = self.synapse.weight-self.lower_limit
            self.synapse.weight -= self.learning_rate * dw * limiter

    def __str__(self):
        return "BSTDP\n"+str(self.A_pos)+","+str(self.A_neg)+","+str(self.tau_pos)+","+str(self.tau_neg)+","+str(self.upper_limit)+"~"+str(self.lower_limit)
