/*******************************************************************************
*   @author Tomáš Pospíšil
*
*   Tento kód byl sestaven na základì tutoriálu, dostupného na adrese:
*   https://docs.juce.com/master/tutorial_handling_midi_events.html .
*
*  ==============================================================================

   Some of the code is part of the JUCE tutorials.
   Copyright (c) 2020 - Raw Material Software Limited

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
   WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
   PURPOSE, ARE DISCLAIMED.

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

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

    This file contains the basic framework code for a JUCE plugin editor.

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

#pragma once

#include <JuceHeader.h>
#include "PluginProcessor.h"

//==============================================================================
/*
* This class is generated by JUCE framework. It contains functions to handle MIDI 
* messages. This project reacts to MIDI messages and prints them to the midiMessagesBox.
* The MIDI messages are sent by controler or by MidiKeyboardComponent.
*/
class MidiTestAudioProcessorEditor  : public juce::AudioProcessorEditor, 
                                      public juce::Component,
                                      private juce::MidiInputCallback,
                                      private juce::MidiKeyboardStateListener
{
public:
    MidiTestAudioProcessorEditor (MidiTestAudioProcessor&);
    ~MidiTestAudioProcessorEditor() override;

    //==============================================================================
    // Function declaration

    void paint (juce::Graphics&) override;
    void resized() override;
    void addMessageToList(const juce::MidiMessage& message, const juce::String& source);

private:
    void setMidiInput(int index);
    static juce::String getMidiMessageDescription(const juce::MidiMessage& m);
    void logMessage(const juce::String& m);
    void handleIncomingMidiMessage(juce::MidiInput* source, const juce::MidiMessage& message) override;
    void handleNoteOn(juce::MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity) override;
    void handleNoteOff(juce::MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity) override;


    /*
    * This class is reacting to incoming MIDI message. It adds the  message and its source to the midiMessageesBox.
    */
    class IncomingMessageCallback : public juce::CallbackMessage
    {
    public:
        IncomingMessageCallback(MidiTestAudioProcessorEditor* p, const juce::MidiMessage& m, const juce::String& s)
            : owner(p), message(m), source(s)
        {}

        void messageCallback() override
        {
            if (owner != nullptr)
                owner->addMessageToList(message, source);
        }

        Component::SafePointer<MidiTestAudioProcessorEditor> owner;
        juce::MidiMessage message;
        juce::String source;
    };
    void postMessageToList(const juce::MidiMessage& message, const juce::String& source);
    

    /*
    * Class objects and variables
    */
    MidiTestAudioProcessor& audioProcessor;

    juce::AudioDeviceManager deviceManager;          
    juce::ComboBox midiInputList;                     
    juce::Label midiInputListLabel;
    int lastInputIndex = 0;                           
    bool isAddingFromMidiInput = false;               

    juce::MidiKeyboardState keyboardState;           
    juce::MidiKeyboardComponent keyboardComponent;    

    juce::TextEditor midiMessagesBox;
    double startTime;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiTestAudioProcessorEditor)
};
