/*
  ==============================================================================

    OSCReceiverWrapper.cpp
    Created: 5 May 2025 2:34:15pm
    Author:  Luigi

  ==============================================================================
*/

#include "OSCReceiverWrapper.h"

OSCReceiverWrapper::OSCReceiverWrapper(int port, juce::AudioProcessorValueTreeState* apvts) {
	this->apvts = apvts;

    this->eqGainRange = new juce::NormalisableRange<float>(MINEQBANDGAIN, MAXEQBANDGAIN);
    this->distortionDriveRange = new juce::NormalisableRange<float>(MINDISTORTIONDRIVE, MAXDISTORTIONDRIVE);

    if (!this->connect(port)) {
        this->oscConnectionError();
    }

    // Declaring the listeners for the iDraw OSC paths
    addListener(this, "/r");
    addListener(this, "/g");
    addListener(this, "/b");
    addListener(this, "/a");
    addListener(this, "/pen");
    addListener(this, "/pencil");
    addListener(this, "/marker");
    addListener(this, "/monoline");
    addListener(this, "/crayon");
    addListener(this, "/fountainPen");
    addListener(this, "/waterColor");
    addListener(this, "/bitmapEraser");
    addListener(this, "/vectorEraser");
    addListener(this, "/canvasWidth");
    addListener(this, "/canvasHeight");
    addListener(this, "/drawingWidth");
    addListener(this, "/eraserWidth");
    addListener(this, "/x");
    addListener(this, "/y");
    addListener(this, "/pressure");
    addListener(this, "/aspectX");
    addListener(this, "/aspectY");
}

OSCReceiverWrapper::~OSCReceiverWrapper() {}

void OSCReceiverWrapper::oscMessageReceived(const juce::OSCMessage& message)
{
    if (!message.isEmpty() && message.size() == 1) {
	    auto address = message.getAddressPattern().toString();
        float argument = 0.0;

        try {
            argument = message[0].getFloat32();
        }
        catch (const std::exception e) {
			return; // Bypass packet intepretation because the argument is not a float
        }

        if (address == "/r") {
            // Unused
        }
        else if (address == "/g") {
            // Unused
        }
        else if (address == "/b") {
            // Unused
        }
        else if (address == "a") {
            // Unused
        }
        // Pen types are used to manage the presets
        else if (address == "/pen") {
            // Unused
        }
        else if (address == "/pencil" && argument == 1.0) {
            this->currentPreset = Preset::PENCIL;
        }
        else if (address == "/marker") {
            // Unused
        }
        else if (address == "/monoline") {
            // Unused
        }
        else if (address == "/crayon" && argument == 1.0) {
            this->currentPreset = Preset::CRAYON;
        }
        else if (address == "/fountainPen") {
            // Preset #3
        }
        else if (address == "/waterColor" && argument == 1.0) {
            this->currentPreset = Preset::WATERCOLOR;
        }
        else if (address == "/bitmapEraser") {
        }
        else if (address == "/vectorEraser") {
        }
        else if (address == "/canvasWidth") {
        }
        else if (address == "/canvasHeight") {
        }
        else if (address == "/drawingWidth") {
            this->thickness = argument;
        }
        else if (address == "/eraserWidth") {
        }
        // Value assignment
        else if (address == "/x") {
        }
        else if (address == "/y") {
        }
        else if (address == "/pressure") {
        }
        else if (address == "/aspectX") {
            this->aspectX = argument;
            this->processMessage();
        }
        else if (address == "/aspectY") {
            this->aspectY = argument;
            this->processMessage();
        }
    }
}

void OSCReceiverWrapper::oscConnectionError() {
    return;
}

void OSCReceiverWrapper::processMessage() {
    if (this->currentPreset == Preset::PENCIL) {
        this->apvts->state.setProperty("REVERBROOMSIZE", this->aspectY + 0.5, nullptr);
    }
    else if (this->currentPreset == Preset::CRAYON) {
        this->apvts->state.setProperty("DELAYAMOUNT", this->aspectX + 0.5, nullptr);
        this->apvts->state.setProperty("REVERBDRYWET", this->aspectY + 0.5, nullptr);
    }
    else if (this->currentPreset == Preset::WATERCOLOR) {
        // Changing parameters of single effects
        if (this->thickness <= 6) { //EQ
            this->apvts->state.setProperty("EQLOWBANDGAIN",
                this->eqGainRange->convertFrom0to1(this->aspectX + 0.5),
                nullptr
            );
            this->apvts->state.setProperty("EQHIGHBANDGAIN",
                this->eqGainRange->convertFrom0to1(this->aspectY + 0.5),
                nullptr
            );
        }
        else if (this->thickness <= 12) { // Dist
            this->apvts->state.setProperty("DISTORTIONMIX", this->aspectX + 0.5, nullptr);
            this->apvts->state.setProperty("DISTORTIONDRIVE",
                this->distortionDriveRange->convertFrom0to1(this->aspectY + 0.5),
                nullptr
            );
        }
        else if (this->thickness <= 18) { // Chorus
            this->apvts->state.setProperty("CHORUSDRYWET", this->aspectX + 0.5, nullptr);
            this->apvts->state.setProperty("CHORUSAMOUNT", this->aspectY + 0.5, nullptr);
        }
        else if (this->thickness <= 24) { // Reverb
            this->apvts->state.setProperty("REVERBDRYWET", this->aspectX + 0.5, nullptr);
            this->apvts->state.setProperty("REVERBROOMSIZE", this->aspectY + 0.5, nullptr);
        }
        else if (this->thickness <= 30) { //Delay
            this->apvts->state.setProperty("DELAYDRYWET", this->aspectX + 0.5, nullptr);
            this->apvts->state.setProperty("DELAYAMOUNT", this->aspectY + 0.5, nullptr);
        }
    }
}