#pragma once

#include <cstring>
#include <stdint.h>

class ByteUtils
{
public:
    using Word = int16_t;
    using DWord = int32_t;
    using QWord = int64_t;

    static bool MostSignificantBitIsOne(char c)
    {
        return c & (1 << 7);
    }

    static Word GetWordFirstBit(const Word word)
    {
        return word & ByteUtils::WORD_FIRST_BIT;
    };

    static Word GetWordLastByte(const Word word)
    {
        return word & ByteUtils::WORD_LAST_BYTE;
    }

    static void ReverseBuffer(char* buffer, char* reverse, unsigned size, unsigned targetSize)
    {
        for(unsigned idx=0; idx<targetSize; idx++)
        {
            if (idx < size)
            {
                reverse[idx] = buffer[size - 1 -idx];
            }
            else
            {
                reverse[idx] = 0;
            }
        }
    }

    template<typename T>
    static T ToType(char* buffer, bool reverse = true)
    {
        T result {0};
        if(reverse)
        {
            char reversed[sizeof(T)];
            ReverseBuffer(buffer, reversed, sizeof(T), sizeof(T));
            std::memcpy(&result, reversed, sizeof(T));
        }
        else
        {
            std::memcpy(&result, buffer, sizeof(T));
        }
        return result;
    }

    static Word ToWord(char* buffer, bool reverse = true)
    {
        return ToType<Word>(buffer, reverse);
    }

    static DWord ToDWord(char* buffer, bool reverse = true)
    {
        return ToType<DWord>(buffer, reverse);
    }

    static QWord ToQWord(char* buffer, bool reverse = true)
    {
        return ToType<QWord>(buffer, reverse);
    }

    static bool Compare(char* buffer, const char* tag, unsigned size)
    {
        for(unsigned idx=0; idx<size; idx++)
        {
            if(tag[idx] != buffer[idx])
            {
                return false;
            }
        }
        return true;
    }

    static bool CompareDWords(char* buffer, const char* tag)
    {
        return Compare(buffer, tag, sizeof(DWord));
    }

    static bool CompareWords(char* buffer, const char* tag)
    {
        return Compare(buffer, tag, sizeof(Word));
    }

    static const int BYTE_FIRST_BIT = 0x40; // 1000 0000
    static const Word WORD_FIRST_BIT = 0x8000; // 1000 0000 - 0000 0000
    static const Word WORD_LAST_BYTE = 0x00FF; // 0000 0000 - 1111 1111
};
