#pragma once

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

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

    static bool MostSignificantBitIsOne(char c);

    static Word GetWordFirstBit(const Word word);

    static Word GetWordLastByte(const Word word);

    static unsigned char getByteN(uint32_t input, unsigned n);

    static unsigned char getHigherNBits(unsigned char input, unsigned num);

    static unsigned char getLowerNBits(uint32_t input, unsigned num);

    static unsigned char getTwoBitsAtN(unsigned char input, unsigned n);

    static unsigned char getMBitsAtN(unsigned char input, unsigned m, unsigned n);

    static bool getBitN(uint32_t input, unsigned n);

    static unsigned char getFromString(const std::string& string);

    static std::string toString(uint32_t input, unsigned length = 8);

    static uint32_t mirror(uint32_t input, unsigned length=0);

    static void ReverseBuffer(char* buffer, char* reverse, unsigned size, unsigned targetSize);

    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);

    static DWord ToDWord(char* buffer, bool reverse = true);

    static QWord ToQWord(char* buffer, bool reverse = true);

    static bool Compare(char* buffer, const char* tag, unsigned size);

    static bool CompareDWords(char* buffer, const char* tag);

    static bool CompareWords(char* buffer, const char* tag);

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