#pragma once
#include <cstring>
#include <iostream>

class ByteUtils
{
public:
    using Word = int;
    using DWord = int;

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

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

    static int 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;
            }
        }
    }

    static int ToInt(char* buffer, const unsigned size, bool reverse = true)
    {
        int result {0};
        if(reverse)
        {
            char reversed[sizeof(int)];
            ReverseBuffer(buffer, reversed, size, sizeof(int));
            std::memcpy(&result, reversed, sizeof(int));
        }
        else
        {
            std::memcpy(&result, buffer, sizeof(int));
        }
        return result;
    }

    static Word ToWord(char* buffer, bool reverse = true)
    {
        return ToInt(buffer, BYTES_PER_WORD, reverse);
    }

    static DWord ToDWord(char* buffer, bool reverse = true)
    {
        return ToInt(buffer, BYTES_PER_DWORD, 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, BYTES_PER_DWORD);
    }

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

    static const int BYTES_PER_WORD = 2;
    static const int BYTES_PER_DWORD = 4;
    static const int BYTE_FIRST_BIT = 0x40; // 1000 0000
    static const int WORD_FIRST_BIT = 0x8000; // 1000 0000 - 0000 0000
    static const int WORD_LAST_BYTE = 0x00FF; // 0000 0000 - 1111 1111
};
