#pragma once

#include "MidiEvent.h"
#include "MidiElements.h"
#include <memory>
#include <string>

class MetaMidiEvent : public MidiEvent
{
public:
    enum class Type
    {
        UNSET,
        UNKNOWN,
        SEQ_NUM,
        TEXT,
        COPYRIGHT,
        TRACK_NAME,
        INSTRUMENT_NAME,
        LYRIC,
        MARKER,
        CUE_POINT,
        CHANNEL_PREFIX,
        END_TRACK,
        SET_TEMPO,
        SMPTE_OFFSET,
        TIME_SIG,
        KEY_SIG,
        SEQ_CUSTOM
    };

private:
    static const int META_SEQ_NUM = 0x0;
    static const int META_TEXT = 0x1;
    static const int META_COPYRIGHT = 0x2;
    static const int META_TRACK_NAME = 0x3; // 0000 0011
    static const int META_INSTRUMENT_NAME = 0x4;
    static const int META_LYRIC = 0x5;
    static const int META_MARKER = 0x6;
    static const int META_CUE_POINT = 0x7;
    static const int META_CHANNEL_PREFIX = 0x20;
    static const int META_END_TRACK = 0x2F;

    static const int META_SET_TEMPO = 0x51; // 0101 0001
    static const int META_SMPTE_OFFSET = 0x54;
    static const int META_TIME_SIG = 0x58; // 0101 1000
    static const int META_KEY_SIG = 0x59; // 0101 1001

    static const int META_SEQ_CUSTOM = 0x7F;

public:

    MetaMidiEvent();
    static std::unique_ptr<MetaMidiEvent> Create();

    void SetValue(int value);
    void SetType(char c);
    Type GetType() const;

    void SetLabel(const std::string& label);
    void SetTimeSignature(const MidiTimeSignature& timeSig);
    void SetTimeCode(const MidiSmtpeTimecode& timeCode);
    void SetKeySignature(const MidiKeySignature& keySig);

private:
    Type mType {Type::UNSET};
    char mUnKnownMarker{0};
    std::string mLabel;
    int mValue { 0 };
    MidiTimeSignature mTimeSig;
    MidiSmtpeTimecode mTimecode;
    MidiKeySignature mKeySig;
};

using MetaMidiEventPtr = std::unique_ptr<MetaMidiEvent>;
