#pragma once

#include "Common.h"
#include "CoreMinimal.h"
#include "lpx-basebuffer.hpp"

class FlxStreamBufferConfig {
private:
	bool err_eof_on_read_;
	bool err_string_too_long_;
	bool err_integer_truncated_;
public:
    using string_type = std::string;
    using fvector_type = FVector;
    using dvector_type = FVector;
    using luavalue_type = LuaValue;
    void *basebuffer_malloc(size_t size) { return malloc(size); }
    void basebuffer_free(void *p) { free(p); }
    void clear_error_flags() { err_eof_on_read_ = err_string_too_long_ = err_integer_truncated_ = false; }
	void raise_eof_on_read() { err_eof_on_read_ = true; }
    void raise_string_too_long() { err_string_too_long_ = true; }
	void raise_integer_truncated() { err_integer_truncated_ = true; }

public:
	bool get_err_eof_on_read() const { return err_eof_on_read_; }
	bool get_err_string_too_long() const { return err_string_too_long_; }
	bool get_err_integer_truncated() const { return err_integer_truncated_; }
	bool any_error() const { return err_eof_on_read_ || err_string_too_long_ || err_integer_truncated_; }
};

class FlxStreamBuffer : public BaseBuffer<FlxStreamBufferConfig> {
public:
    using BaseBuffer::BaseBuffer;
    using BaseBuffer::write_string;

    void write_string(const FString &str) {
	    FTCHARToUTF8 utf8str(str);
        write_string(std::string_view(utf8str.Get(), utf8str.Length()));
    }

    void write_fname(const FName &name) {
	    FTCHARToUTF8 utf8str(name.ToString());
        write_string(std::string_view(utf8str.Get(), utf8str.Length()));
    }

    void write_string(const char *s) {
        write_string(std::string_view(s));
    }

    void write_fvector(const FVector &xyz) {
        write_double(xyz.X);
        write_double(xyz.Y);
        write_double(xyz.Z);
    }

    FVector read_fvector() {
        double x = read_double();
        double y = read_double();
        double z = read_double();
        return FVector(x, y, z);
    }

    FString read_fstring() {
        std::string_view s = read_string_view();
	    return FString(s.size(), (const UTF8CHAR *)s.data());
    }

    FName read_fname() {
        std::string_view s = read_string_view();
        return FName(s.size(), (const UTF8CHAR *)s.data(), FNAME_Add);
    }
};
