#include "gainbalance.h"
using Xybrid::Gadgets::GainBalance;
using namespace Xybrid::Data;

#include "nodelib/basics.h"
using namespace Xybrid::NodeLib;

#include "data/audioframe.h"
#include "data/porttypes.h"

#include "config/pluginregistry.h"
using namespace Xybrid::Config;

#include "audio/audioengine.h"
using namespace Xybrid::Audio;

#include "ui/patchboard/nodeobject.h"
#include "ui/gadgets/layoutgadget.h"
#include "ui/gadgets/knobgadget.h"
using namespace Xybrid::UI;

#include <cmath>

#include <QCborMap>

#define qs QStringLiteral

namespace {
    bool _ = PluginRegistry::enqueueRegistration([] {
        auto i = std::make_shared<PluginInfo>();
        i->id = "gadget:gainbalance";
        i->displayName = "Gain/Balance";
        i->category = "Gadget";
        //i->hidden = true;
        i->createInstance = []{ return std::make_shared<GainBalance>(); };
        PluginRegistry::registerPlugin(i);
        //inf = i;
    });
}

GainBalance::GainBalance() {

}

void GainBalance::init() {
    addPort(Port::Input, Port::Audio, 0);
    addPort(Port::Output, Port::Audio, 0);
}

void GainBalance::process() { // TODO: lerp from tick to tick?
    auto m = AudioFrame::gainBalanceMult(gain.load(), balance.load());

    auto in = std::static_pointer_cast<AudioPort>(port(Port::Input, Port::Audio, 0));
    auto out = std::static_pointer_cast<AudioPort>(port(Port::Output, Port::Audio, 0));
    in->pull();
    out->pull();

    size_t ts = audioEngine->curTickSize();
    for (size_t s = 0; s < ts; s++) (*out)[s] = (*in)[s] * m;
}

void GainBalance::saveData(QCborMap& m) const {
    m[qs("gain")] = QCborValue(gain);
    m[qs("balance")] = QCborValue(balance);
}

void GainBalance::loadData(const QCborMap& m) {
    gain = m.value("gain").toDouble(0.0);
    balance = m.value("balance").toDouble(0.0);
}

void GainBalance::onGadgetCreated() {
    if (!obj) return;
    obj->showPluginName = false;
    auto l = new LayoutGadget(obj);

    (new KnobGadget(l))->bind(gain)->setRange(-60, 6, .1)->setLabel("Gain")->setTextFunc([](double d) { return QString("%1dB").arg(d); });
    (new KnobGadget(l))->bind(balance)->setRange(-1.0, 1.0)->setLabel("Balance");
}
