#include "gralloc4/gralloc_vendor_interface.h"
#include <vector>
#include <sys/stat.h>

#include "core/format_info.h"
#include "core/mali_gralloc_bufferdescriptor.h"
#include "core/mali_gralloc_bufferallocation.h"
#include "allocator/mali_gralloc_ion.h"
#include "hidl_common/SharedMetadata.h"
#include "gralloc_priv.h"

namespace android::hardware::graphics::allocator::priv {

struct Descriptor {
    unsigned int size = 0;
    uint64_t producer_usage = 0;
    uint64_t consumer_usage = 0;

    struct PlaneDescriptor {
        int fd = -1;
        size_t size = 0;
        off_t offset = 0;
        int stride_byte = 0;
    };
    std::vector<PlaneDescriptor> planes;

    int width = 0;
    int height = 0;
    int stride_pixel = 0;
    int format = 0;
};

Descriptor *createDescriptor() { return new Descriptor(); }
void deleteDescriptor(Descriptor *descriptor) { delete descriptor; }

void setProducerUsage(Descriptor &descriptor, uint64_t usage) {
    descriptor.producer_usage = usage;
}

void setConsumerUsage(Descriptor &descriptor, uint64_t usage) {
    descriptor.consumer_usage = usage;
}

void setPlaneCount(Descriptor &descriptor, int count) {
    descriptor.planes.resize(count);
}

void setPlane(Descriptor &descriptor, int index, int fd, size_t size, off_t offset, int stride_byte) {
    descriptor.planes[index].fd = fd;
    descriptor.planes[index].size = size;
    descriptor.planes[index].offset = offset;
    descriptor.planes[index].stride_byte = stride_byte;
}

void setWidth(Descriptor &descriptor, int width) {
    descriptor.width = width;
}

void setHeight(Descriptor &descriptor, int height) {
    descriptor.height = height;
}

void setStridePixel(Descriptor &descriptor, int stride_pixel) {
    descriptor.stride_pixel = stride_pixel;
}

void setFormat(Descriptor &descriptor, int format) {
    descriptor.format = format;
}

buffer_handle_t createNativeHandle(const Descriptor &descriptor) {
    for (int i = 0; i < descriptor.planes.size(); ++i) {
        struct stat st;
        fstat(descriptor.planes[i].fd, &st);
        off64_t fd_size = st.st_size;
        if (fd_size < descriptor.planes[i].size) {
            ALOGE("libGralloc4Wrapper: createNativeHandle failed: plane[%d] requested size greater than fd size.",
                i);
            return nullptr;
        }
    }

    buffer_descriptor_t buffer_descriptor;

    buffer_descriptor.pixel_stride = descriptor.stride_pixel;
    buffer_descriptor.width = descriptor.width;
    buffer_descriptor.height = descriptor.height;
    buffer_descriptor.layer_count = 1;
    buffer_descriptor.hal_format = buffer_descriptor.alloc_format
        = descriptor.format;
    buffer_descriptor.producer_usage = descriptor.producer_usage;
    buffer_descriptor.consumer_usage = descriptor.consumer_usage;
    buffer_descriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
    buffer_descriptor.signature = sizeof(buffer_descriptor_t);

    buffer_descriptor.fd_count = buffer_descriptor.plane_count
        = descriptor.planes.size();
    for (int i = 0; i < descriptor.planes.size(); ++i) {
        buffer_descriptor.alloc_sizes[i] = descriptor.planes[i].size;
    }

    auto format_index = get_format_index(descriptor.format);
    if (format_index == -1) {
        ALOGE("libGralloc4Wrapper: invalid format 0x%x",
            descriptor.format);
        return 0;
    }
    for (int i = 0; i < descriptor.planes.size(); ++i) {
        uint8_t bpp = formats[format_index].bpp[i];
        if (bpp == 0) {
            ALOGE("libGralloc4Wrapper: format 0x%x has bpp[%d]=0",
                descriptor.format, i);
            return nullptr;
        }
        buffer_descriptor.plane_info[i] = {
            .byte_stride = static_cast<uint32_t>((descriptor.planes[i].stride_byte * bpp) / 8),
            .alloc_width = buffer_descriptor.width,
            .alloc_height = buffer_descriptor.height,
        };
    }

    if (mali_gralloc_derive_format_and_size(&buffer_descriptor)) {
        ALOGE("libGralloc4Wrapper: mali_gralloc_derive_format_and_size failed");
        return nullptr;
    }

    const gralloc_buffer_descriptor_t gralloc_buffer_descriptor =
        reinterpret_cast<const gralloc_buffer_descriptor_t>(&buffer_descriptor);

    buffer_handle_t tmp_buffer;
    bool shared_backend;
    // TODO(modan@, make mali_gralloc_ion_allocate accept multiple fds)
    {
        int result = mali_gralloc_buffer_allocate(&gralloc_buffer_descriptor, 1, &tmp_buffer,
            &shared_backend, descriptor.planes[0].fd);
        if (result < 0) {
            ALOGE("mali_gralloc_buffer_allocate failed");
            return nullptr;
        }
    }

    private_handle_t *hnd = const_cast<private_handle_t *>(
        static_cast<const private_handle_t *>(tmp_buffer));

    hnd->imapper_version = HIDL_MAPPER_VERSION_SCALED;

    hnd->reserved_region_size = buffer_descriptor.reserved_size;
    hnd->attr_size = arm::mapper::common::shared_metadata_size() + hnd->reserved_region_size;

    {
        int result = mali_gralloc_ion_allocate_attr(hnd);
        if (result < 0) {
            ALOGE("mali_gralloc_ion_allocate_attr failed");
            mali_gralloc_buffer_free(tmp_buffer);
            return nullptr;
        }
    }

    {
        auto metadata_vaddr = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE,
                MAP_SHARED, hnd->get_share_attr_fd(), 0);
        if (metadata_vaddr == MAP_FAILED) {
            ALOGE("mmap hnd->get_share_attr_fd() failed");
            mali_gralloc_buffer_free(tmp_buffer);
            return nullptr;
        }

        memset(metadata_vaddr, 0, hnd->attr_size);

        arm::mapper::common::shared_metadata_init(metadata_vaddr, buffer_descriptor.name);

        const uint32_t base_format = buffer_descriptor.alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
        const uint64_t usage = buffer_descriptor.consumer_usage | buffer_descriptor.producer_usage;
        android_dataspace_t dataspace;
        get_format_dataspace(base_format, usage, hnd->width, hnd->height, &dataspace);

        {
            using arm::mapper::common::aligned_optional;
            using arm::mapper::common::Dataspace;
            using arm::mapper::common::shared_metadata;
            (static_cast<shared_metadata *>(metadata_vaddr))->dataspace =
                    aligned_optional(static_cast<Dataspace>(dataspace));
        }

        munmap(metadata_vaddr, hnd->attr_size);
    }

    // TODO(modan@, handle all plane offsets)
    hnd->offset = hnd->plane_info[0].offset = descriptor.planes[0].offset;
    hnd->layer_count = 1;

    return tmp_buffer;
}

int freeImportedHandle(void *handle)
{
    using android::hardware::graphics::mapper::V4_0::IMapper;
    using android::hardware::graphics::mapper::V4_0::Error;

    const private_handle_t *hnd = static_cast<private_handle_t *>(handle);

    static android::sp<IMapper> mapper = IMapper::getService();
    if (!mapper)
    {
        ALOGE("libGralloc4Wrapper: %s failed to get a mapper", __func__);
        return -1;
    }

    if (mapper->freeBuffer(handle) != Error::NONE)
    {
        ALOGE("libGralloc4Wrapper: %s couldn't freeBuffer(%p\n", __func__, handle);
        return -1;
    }

    return 0;
}

}  // namespace android::hardware::graphics::allocator::priv
