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

    Settings.h
    Created: 23 May 2019 11:54:44am
    Author:  除村 武志

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

#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
#include "ColorScheme.h"
#include "FrameSequence.h"
#include "FrameSequenceParseErrors.h"

//---------------------------------------------
//
// Plugin Global
//
//---------------------------------------------
enum VoiceType
{
    kVoiceTypePulse = 0,
    kVoiceTypeTriangle,
    kVoiceTypeNoise
};

struct PluginSettings
{
    VoiceType type = kVoiceTypePulse;
    int maxPoly = 1;
    double gain = 1.0;
    double arpeggioTime = 0;
    double bendRange = 2;
};

//---------------------------------------------
//
// Tone Specific
//
//---------------------------------------------
enum PulseDuty
{
    kPulseDuty125 = 0,
    kPulseDuty250,
    kPulseDuty500,
};

enum NoiseAlgorithm
{
    kNoiseInfinite2 = 0,
    kNoiseLong,
    kNoiseShort,
};

enum PitchSequenceMode
{
    kPitchSequenceModeCoarse = 0,
    kPitchSequenceModeFine
};

class FrameSequenceChangeListener
{
public:
    FrameSequenceChangeListener() {}
    virtual ~FrameSequenceChangeListener() {};
    virtual void sequenceChanged (String& str) {};
};


struct FrameSequenceParseException
{
    String message;
    bool isFatal;

    FrameSequenceParseException (String mes, bool fatalFlag)
    {
        message = mes;
        isFatal = fatalFlag;
    }
};

struct SettingRefs
{
    // Meta
    float* isAdvancedPanelOpen_raw = nullptr;
    float* colorScheme = nullptr;
    // Basic
    float* osc = nullptr;
    float* gain = nullptr;
    float* maxPoly = nullptr;
    // ADSR
    float* attack = nullptr;
    float* decay = nullptr;
    float* suslevel = nullptr;
    float* release = nullptr;
    // Arpeggio
    float* isArpeggioEnabled_raw = nullptr;
    float* arpeggioTime = nullptr;
    float* arpeggioDirection = nullptr;
    // Bend
    float* bendRange = nullptr;
    // Vibrato
    float* vibratoRate = nullptr;
    float* vibratoDepth = nullptr;
    float* vibratoDelay = nullptr;
    float* vibratoIgnoresWheel_raw = nullptr;
    // Sweep
    float* sweepInitialPitch = nullptr;
    float* sweepTime = nullptr;
    // For Pulse
    float* duty = nullptr;
    // For Noise
    float* noiseAlgorithm_raw = nullptr;
    float* restrictsToNESFrequency_raw = nullptr;
    // Sequence
    float* isVolumeSequenceEnabled_raw = nullptr;
    float* isPitchSequenceEnabled_raw = nullptr;
    float* isDutySequenceEnabled_raw = nullptr;
    float* pitchSequenceMode_raw = nullptr;

    FrameSequence volumeSequence;
    FrameSequence pitchSequence;
    FrameSequence dutySequence;
    String volumeSequenceString = "";
    String pitchSequenceString = "";
    String dutySequenceString = "";

    bool setSequenceWithString (const String& type, const String& input, ParseError* error);
    String& getSequenceString (const String& type);

    FrameSequence parseSequenceString (const String& input);
    FrameSequenceChangeListener* volumeSequenceListener = nullptr;
    FrameSequenceChangeListener* pitchSequenceListener = nullptr;
    FrameSequenceChangeListener* dutySequenceListener = nullptr;

    //
    // accessors
    //
    int oscillatorType() { return (int) (*osc); }
    bool isAdvancedPanelOpen() { return *isAdvancedPanelOpen_raw > 0.5; }
    ColorSchemeType colorSchemeType() { return (ColorSchemeType) ((int) (*colorScheme)); }

    bool isArpeggioEnabled() { return *isArpeggioEnabled_raw > 0.5; }
    NoiseAlgorithm noiseAlgorithm() { return (NoiseAlgorithm) ((int) (*noiseAlgorithm_raw)); }

    bool vibratoIgnoresWheel() { return *vibratoIgnoresWheel_raw > 0.5; }

    bool isVolumeSequenceEnabled() { return *isVolumeSequenceEnabled_raw > 0.5; }
    bool isPitchSequenceEnabled() { return *isPitchSequenceEnabled_raw > 0.5; }
    bool isDutySequenceEnabled() { return *isDutySequenceEnabled_raw > 0.5; }
    PitchSequenceMode pitchSequenceMode() { return (PitchSequenceMode) ((int) (*pitchSequenceMode_raw)); }


    //
    // constructor
    //
    SettingRefs (AudioProcessorValueTreeState* parameters)
    {
        // Meta
        isAdvancedPanelOpen_raw = parameters->getRawParameterValue ("isAdvancedPanelOpen_raw");
        colorScheme = parameters->getRawParameterValue ("colorScheme");
        // Basic
        osc = parameters->getRawParameterValue ("osc");
        gain = parameters->getRawParameterValue ("gain");
        maxPoly = parameters->getRawParameterValue ("maxPoly");
        // ADSR
        attack = parameters->getRawParameterValue ("attack");
        decay = parameters->getRawParameterValue ("decay");
        suslevel = parameters->getRawParameterValue ("suslevel");
        release = parameters->getRawParameterValue ("release");
        // Arpeggio
        isArpeggioEnabled_raw = parameters->getRawParameterValue ("isArpeggioEnabled_raw");
        arpeggioTime = parameters->getRawParameterValue ("arpeggioTime");
        arpeggioDirection = parameters->getRawParameterValue ("arpeggioDirection");
        // Bend
        bendRange = parameters->getRawParameterValue ("bendRange");
        // Vibrato
        vibratoRate = parameters->getRawParameterValue ("vibratoRate");
        vibratoDepth = parameters->getRawParameterValue ("vibratoDepth");
        vibratoDelay = parameters->getRawParameterValue ("vibratoDelay");
        vibratoIgnoresWheel_raw = parameters->getRawParameterValue ("vibratoIgnoresWheel_raw");
        // Sweep
        sweepInitialPitch = parameters->getRawParameterValue ("sweepInitialPitch");
        sweepTime = parameters->getRawParameterValue ("sweepTime");
        // For Pulse
        duty = parameters->getRawParameterValue ("duty");
        // For Noise
        noiseAlgorithm_raw = parameters->getRawParameterValue ("noiseAlgorithm_raw");
        restrictsToNESFrequency_raw = parameters->getRawParameterValue ("restrictsToNESFrequency_raw");
        // Sequence
        isVolumeSequenceEnabled_raw = parameters->getRawParameterValue ("isVolumeSequenceEnabled_raw");
        isPitchSequenceEnabled_raw = parameters->getRawParameterValue ("isPitchSequenceEnabled_raw");
        isDutySequenceEnabled_raw = parameters->getRawParameterValue ("isDutySequenceEnabled_raw");
        pitchSequenceMode_raw = parameters->getRawParameterValue ("pitchSequenceMode_raw");

    }
};