import numpy
import matplotlib.pyplot as plt

from matplotlib.widgets import Button, Slider

# series RLC, drop across the cap, natural response

def f(t, R, L, C, v_o, v_i, i_o):
    alpha = R / (2 * L)
    omega_0 = 1 / (numpy.sqrt(L * C))
    omega_d = numpy.sqrt(omega_0**2 - alpha**2, dtype=complex)
    if omega_d == 0:
        omega_d = numpy.finfo(float).eps

    X = v_o - v_i
    Y = -1 * ((i_o / C) + alpha * X) / omega_d
    A = numpy.sqrt(Y**2 + X**2)
    phi = numpy.atan(Y / X)
    if X < 0:
        A = A * -1
    return (A) * numpy.e ** (-alpha * t) * numpy.cos((omega_d) * t + phi) + v_i


t = numpy.linspace(0, 1e-2, int(1e3))

init_R = 1.7
init_L = -2
init_C = -6
init_vo = 6
init_v1 = 2
init_io = 0.06

fig, ax = plt.subplots()
ax.set_xlabel("Time [ms]")
ax.set_yticks([])

fig.subplots_adjust(bottom=0.45)

axr = fig.add_axes([0.15, 0.3, 0.65, 0.03])
R_slider = Slider(
    ax=axr,
    label=r"$R$",
    valmin=-3,
    valmax=3,
    valinit=init_R,
)

axl = fig.add_axes([0.15, 0.25, 0.65, 0.03])
L_slider = Slider(
    ax=axl,
    label=r"$L$",
    valmin=-9,
    valmax=0,
    valinit=init_L,
)
axl = fig.add_axes([0.15, 0.2, 0.65, 0.03])
C_slider = Slider(
    ax=axl,
    label=r"$C$",
    valmin=-9,
    valmax=0,
    valinit=init_C,
)
axl = fig.add_axes([0.15, 0.15, 0.65, 0.03])
v1_slider = Slider(
    ax=axl,
    label=r"$V_{source}$",
    valmin=-10,
    valmax=10,
    valinit=init_v1,
)
axl = fig.add_axes([0.15, 0.1, 0.65, 0.03])
vo_slider = Slider(
    ax=axl,
    label=r"$v_{C,init}$",
    valmin=-10,
    valmax=10,
    valinit=init_vo,
)
axl = fig.add_axes([0.15, 0.05, 0.65, 0.03])
io_slider = Slider(
    ax=axl,
    label=r"$i_{L,init}$",
    valmin=-1,
    valmax=1,
    valinit=init_io,
)


def update(val):
    R_slider.valtext.set_text("10^(%.02f) $\Omega$" % R_slider.val)
    C_slider.valtext.set_text("10^(%.02f) F" % C_slider.val)
    L_slider.valtext.set_text("10^(%.02f) H" % L_slider.val)
    io_slider.valtext.set_text("%.02f A" % io_slider.val)
    vo_slider.valtext.set_text("%.02f V" % vo_slider.val)
    v1_slider.valtext.set_text("%.02f V" % v1_slider.val)
    ax.clear()
    ax.plot(
        t * 1e3,
        f(
            t,
            10**R_slider.val,
            10**L_slider.val,
            10**C_slider.val,
            vo_slider.val,
            v1_slider.val,
            io_slider.val,
        ),
    )
    omega_0 = 1 / (numpy.sqrt(10**L_slider.val * 10**C_slider.val))
    alpha = 10**R_slider.val / (2 * 10**L_slider.val)
    ax.grid()
    ax.axis([0, 10, -10, 10])
    ax.text(8.25, -9, "Q = %.03f" % (omega_0 / (2 * alpha)), fontsize=14, color="green")
    ax.set_xlabel("Time [ms]")
    ax.set_ylabel("Capacitor Voltage [V]")
    fig.canvas.draw_idle()


ALL_SLIDERS = [
  R_slider, C_slider,
  L_slider,
  vo_slider,
  v1_slider,
  io_slider,
]

update(None)
for slider in ALL_SLIDERS:
    slider.on_changed(update)
resetax = fig.add_axes([0.8, 0.9, 0.1, 0.04])
button = Button(resetax, "Reset", hovercolor="0.975")


def reset(event):
    for slider in ALL_SLIDERS:
        slider.reset()

button.on_clicked(reset)

plt.show()
