// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <optional>
#include <boost/icl/interval_set.hpp>
#include "common/common_types.h"

namespace Kernel {

struct AddressMapping;
class VMManager;

struct MemoryRegionInfo {
    u32 base; // Not an address, but offset from start of FCRAM
    u32 size;
    u32 used;

    // The domain of the interval_set are offsets from start of FCRAM
    using IntervalSet = boost::icl::interval_set<u32>;
    using Interval = IntervalSet::interval_type;

    IntervalSet free_blocks;

    /**
     * Reset the allocator state
     * @param base The base offset the beginning of FCRAM.
     * @param size The region size this allocator manages
     */
    void Reset(u32 base, u32 size);

    /**
     * Allocates memory from the heap.
     * @param size The size of memory to allocate.
     * @returns The set of blocks that make up the allocation request. Empty set if there is no
     *     enough space.
     */
    IntervalSet HeapAllocate(u32 size);

    /**
     * Allocates memory from the linear heap with specific address and size.
     * @param offset the address offset to the beginning of FCRAM.
     * @param size size of the memory to allocate.
     * @returns true if the allocation is successful. false if the requested region is not free.
     */
    bool LinearAllocate(u32 offset, u32 size);

    /**
     * Allocates memory from the linear heap with only size specified.
     * @param size size of the memory to allocate.
     * @returns the address offset to the beginning of FCRAM; null if there is no enough space
     */
    std::optional<u32> LinearAllocate(u32 size);

    /**
     * Frees one segment of memory. The memory must have been allocated as heap or linear heap.
     * @param offset the region address offset to the beginning of FCRAM.
     * @param size the size of the region to free.
     */
    void Free(u32 offset, u32 size);
};

} // namespace Kernel
