#pragma once
/*
 * Machine generated file
 * --RE_DATE--
 * --RE_VERSION--
 * --RE_NAME--
 */

#include "Constants.h"

// 12th root of 2
#define kSemiToneFrequencyMultiplier 1.05946309435929

--CONSTANTS--

typedef struct OmNote {
    TJBox_UInt32 pitch;
    TJBox_Float32 oldVel;
    TJBox_Float32 vel;
} OmNote;

class Om {
private:
    TJBox_ObjectRef transport;
    TJBox_ObjectRef environment;

    TJBox_ObjectRef getTransport() {
        if(!this->transport)
            this->transport = JBox_GetMotherboardObjectRef("/transport");
        return this->transport;
    }
    TJBox_ObjectRef getEnvironment() {
        if(!this->environment)
            this->environment = JBox_GetMotherboardObjectRef("/environment");
        return this->environment;
    }

    static int equalString(const char *a,const char *b)
    {
        while(*a)
            if(*a++ != *b++)
                return 0;
        return 1;
    }

public:
    TJBox_ObjectRef props;

    TJBox_UInt32 noteChangeCount;
#define NOTE_CHANGE_MAX 2000
    OmNote noteChanges[NOTE_CHANGE_MAX]; // sometimes, reason gives us many note changes at the beginning. fine.

    void addNoteChange(TJBox_UInt32 pitch,TJBox_Float32 vel)
    {
        if(this->noteChangeCount >= NOTE_CHANGE_MAX) // safety first.
            return;

        if(pitch > 127)
            return;
        if(vel < 0)
            vel = 0;
        if(vel > 127)
            vel = 127;
        OmNote *note = this->noteChanges + this->noteChangeCount++;
        note->pitch = pitch;
        note->oldVel = this->noteVels[pitch];
        this->noteVels[pitch] = vel;
        note->vel = this->noteVels[pitch];
    }

    void doDiffs(const TJBox_PropertyDiff iPropertyDiffs[], TJBox_UInt32 iDiffCount)
    {
        this->transport = 0;
        this->environment = 0;

        this->sysSystemSampleRate = 0;
        this->sysMasterTune = 0;
        
        this->sysFilteredTempo = 0;
        this->sysPlayPos = 0;
        this->sysTimeSignatureNumerator = 0;
        this->sysTimeSignatureDenominator = 0;
        this->sysRequestResetAudio = 0;

        this->noteChangeCount = 0;

        if(iDiffCount == 0)
            return;

        TJBox_ObjectRef notes = JBox_GetMotherboardObjectRef("/note_states");
        this->props = JBox_GetMotherboardObjectRef("/custom_properties");
        for(TJBox_UInt32 i = 0; i < iDiffCount; i++)
        {
            const TJBox_PropertyDiff *d = &iPropertyDiffs[i];
            TJBox_ObjectRef dRef = d->fPropertyRef.fObject;
            TJBox_Tag dTag = d->fPropertyTag;
            if(dRef == notes) 
            {
                this->addNoteChange(dTag,(float)JBox_GetNumber(d->fCurrentValue));
            }
            else if(dRef == props)
            {
                switch(dTag)
                {
--DIFFCASES--
                }
            }
        }
    }

    TJBox_Float32 noteVels[128];

// Input Parameters
--VARIABLES--

// Output Lamps & Meters
--OUTPUTS--

--GETTERS--

    TJBox_Float32 getNumberByPropertyTag(int propertyTag) {
        switch(propertyTag) {
--NUMBER_GET_CASES--
        
        default: return 0;
        }
    }

    TJBox_Bool getBooleanByPropertyTag(int propertyTag) {
        switch(propertyTag) {
--BOOL_GET_CASES--
        
        default: return false;
        }
    }

    void setNumberByPropertyTag(int propertyTag,TJBox_Float32 v) {
        switch(propertyTag) {
--NUMBER_SET_CASES--
        }
    }

    void setBooleanByPropertyTag(int propertyTag,TJBox_Bool v) {
        switch(propertyTag) {
--BOOL_SET_CASES--
        }
    }

    void getAudioByPropertyTag(int propertyTag,TJBox_AudioSample *samplesGot) {
        switch(propertyTag) {
--AUDIO_GET_CASES--
        }
    }
    TJBox_Bool isConnectedByPropertyTag(int propertyTag) {
        TJBox_Bool v = false;
        switch(propertyTag) {
--IS_CONNECTED_CASES--
        }
        return v;
    }

    // +-------------
    // | Some system values
    // |

    #define GETJNUMBER(_group,_type,_name) \
    _type sys##_name; \
    _type get##_name() { \
        if(!this->sys##_name) \
            this->sys##_name = (_type)JBox_LoadMOMPropertyAsNumber(get##_group(), kJBox_##_group##_name); \
        return this->sys##_name; \
    }

    // in hz
    GETJNUMBER(Environment,TJBox_Float32,SystemSampleRate)

    // in cents -100 to +100, centered at 440 A.
    GETJNUMBER(Environment,TJBox_Float32,MasterTune)
    
    // in bpm
    GETJNUMBER(Transport,TJBox_Float32,FilteredTempo)
    // in 15360 per quarter note
    GETJNUMBER(Transport,TJBox_Float32,PlayPos)
    GETJNUMBER(Transport,int,TimeSignatureNumerator)
    GETJNUMBER(Transport,int,TimeSignatureDenominator)
    GETJNUMBER(Transport,TJBox_Float32,RequestResetAudio)

    TJBox_Bool isPlaying() {
        TJBox_Bool v = JBox_GetBoolean(JBox_LoadMOMPropertyByTag(getTransport(), kJBox_TransportPlaying));
        return v;
    }
};

