#include "MidiChannelEvent.h"

MidiChannelEvent::MidiChannelEvent()
    : MidiEvent(),
      mType(Type::NONE),
      mValue0(0),
      mValue1(0)
{

}

std::unique_ptr<MidiChannelEvent> MidiChannelEvent::Create()
{
    return std::make_unique<MidiChannelEvent>();
}

void MidiChannelEvent::SetType(Type type)
{
    mType = type;
}
MidiChannelEvent::Type MidiChannelEvent::GetType() const
{
    return mType;
}
void MidiChannelEvent::SetValues(int value0, int value1)
{
    mValue0 = value0;
    mValue1 = value1;
}
int MidiChannelEvent::GetValue0() const
{
    return mValue0;
}
int MidiChannelEvent::GetValue1() const
{
    return mValue1;
}

void MidiChannelEvent::SetTypeAndChannel(char c)
{
    const int first_four_bits = 0xF0;
    const int second_four_bits = 0xF;
    const int event_type = (c & first_four_bits) >> 4;

    const bool isSystemMessage = event_type == 0xF;
    if(!isSystemMessage)
    {
        mChannel = (c & second_four_bits) >> 4;
        switch(event_type)
        {
        case NOTE_OFF:
            mType = Type::NOTE_OFF;
            break;
        case NOTE_ON:
            mType = Type::NOTE_ON;
            break;
        case NOTE_AFTERTOUCH:
            mType = Type::NOTE_AFTERTOUCH;
            break;
        case CONTROLLER:
            mType = Type::CONTROLLER;
            break;
        case PROGRAM:
            mType = Type::PROGRAM;
            break;
        case CHANNEL_AFTERTOUCH:
            mType = Type::CHANNEL_AFTERTOUCH;
            break;
        case PITCH_BEND:
            mType = Type::PITCH_BEND;
            break;
        }
    }
    else
    {
        const int subType = (c & second_four_bits) >> 4;
        switch(subType)
        {
        case SYS_EXCLUSIVE:
            mType = Type::SYS_EXCLUSIVE;
            break;
        case SYS_SONG_POS:
            mType = Type::SYS_SONG_POS;
            break;
        case SYS_SONG_SELECT:
            mType = Type::SYS_SONG_SELECT;
            break;
        case SYS_TUNE_REQUEST:
            mType = Type::SYS_TUNE_REQUEST;
            break;
        case SYS_END_EXCLUSIVE:
            mType = Type::SYS_END_EXCLUSIVE;
            break;
        case SYS_TIMING_CLOCK:
            mType = Type::SYS_TIMING_CLOCK;
            break;
        case SYS_START:
            mType = Type::SYS_START;
            break;
        case SYS_CONTINUE:
            mType = Type::SYS_CONTINUE;
            break;
        case SYS_STOP:
            mType = Type::SYS_STOP;
            break;
        case SYS_ACTIVE_SENSING:
            mType = Type::SYS_ACTIVE_SENSING;
            break;
        case SYS_RESET:
            mType = Type::SYS_RESET;
            break;
        }
    }
}
