// Copyright 2024 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "ANativeWindowEmulated.h"

#include <log/log.h>

#include "drm_fourcc.h"

namespace gfxstream {

EmulatedANativeWindow::EmulatedANativeWindow(
    uint32_t width, uint32_t height, uint32_t format,
    std::vector<std::unique_ptr<EmulatedAHardwareBuffer>> buffers)
    : mRefCount(1), mWidth(width), mHeight(height), mFormat(format), mBuffers(std::move(buffers)) {
    for (auto& buffer : mBuffers) {
        mBufferQueue.push_back(QueuedAHB{
            .ahb = buffer.get(),
            .fence = -1,
        });
    }
}

EGLNativeWindowType EmulatedANativeWindow::asEglNativeWindowType() {
    return reinterpret_cast<EGLNativeWindowType>(this);
}

uint32_t EmulatedANativeWindow::getWidth() const { return mWidth; }

uint32_t EmulatedANativeWindow::getHeight() const { return mHeight; }

int EmulatedANativeWindow::getFormat() const { return mFormat; }

int EmulatedANativeWindow::queueBuffer(EGLClientBuffer buffer, int fence) {
    auto ahb = reinterpret_cast<EmulatedAHardwareBuffer*>(buffer);

    mBufferQueue.push_back(QueuedAHB{
        .ahb = ahb,
        .fence = fence,
    });

    return 0;
}

int EmulatedANativeWindow::dequeueBuffer(EGLClientBuffer* buffer, int* fence) {
    auto queuedAhb = mBufferQueue.front();
    mBufferQueue.pop_front();

    *buffer = queuedAhb.ahb->asEglClientBuffer();
    *fence = queuedAhb.fence;
    return 0;
}

int EmulatedANativeWindow::cancelBuffer(EGLClientBuffer buffer) {
    auto ahb = reinterpret_cast<EmulatedAHardwareBuffer*>(buffer);

    mBufferQueue.push_back(QueuedAHB{
        .ahb = ahb,
        .fence = -1,
    });

    return 0;
}

void EmulatedANativeWindow::acquire() { ++mRefCount; }

void EmulatedANativeWindow::release() {
    --mRefCount;
    if (mRefCount == 0) {
        delete this;
    }
}

bool EmulatedANativeWindowHelper::isValid(EGLNativeWindowType window) {
    // TODO: maybe a registry of valid EmulatedANativeWindow-s?
    (void)window;
    return true;
}

bool EmulatedANativeWindowHelper::isValid(EGLClientBuffer buffer) {
    // TODO: maybe a registry of valid EmulatedAHardwareBuffer-s?
    (void)buffer;
    return true;
}

void EmulatedANativeWindowHelper::acquire(EGLNativeWindowType window) {
    auto* anw = reinterpret_cast<EmulatedANativeWindow*>(window);
    anw->acquire();
}

void EmulatedANativeWindowHelper::release(EGLNativeWindowType window) {
    auto* anw = reinterpret_cast<EmulatedANativeWindow*>(window);
    anw->release();
}

void EmulatedANativeWindowHelper::acquire(EGLClientBuffer buffer) {
    // TODO: maybe a registry of valid EmulatedAHardwareBuffer-s?
    (void)buffer;
}

void EmulatedANativeWindowHelper::release(EGLClientBuffer buffer) { (void)buffer; }

int EmulatedANativeWindowHelper::getConsumerUsage(EGLNativeWindowType window, int* usage) {
    (void)window;
    (void)usage;
    return 0;
}
void EmulatedANativeWindowHelper::setUsage(EGLNativeWindowType window, int usage) {
    (void)window;
    (void)usage;
}

int EmulatedANativeWindowHelper::getWidth(EGLNativeWindowType window) {
    auto anw = reinterpret_cast<EmulatedANativeWindow*>(window);
    return anw->getWidth();
}

int EmulatedANativeWindowHelper::getHeight(EGLNativeWindowType window) {
    auto anw = reinterpret_cast<EmulatedANativeWindow*>(window);
    return anw->getHeight();
}

int EmulatedANativeWindowHelper::getWidth(EGLClientBuffer buffer) {
    auto ahb = reinterpret_cast<EmulatedAHardwareBuffer*>(buffer);
    return ahb->getWidth();
}

int EmulatedANativeWindowHelper::getHeight(EGLClientBuffer buffer) {
    auto ahb = reinterpret_cast<EmulatedAHardwareBuffer*>(buffer);
    return ahb->getHeight();
}

int EmulatedANativeWindowHelper::getFormat(EGLClientBuffer buffer, Gralloc* helper) {
    (void)helper;

    auto ahb = reinterpret_cast<EmulatedAHardwareBuffer*>(buffer);
    return ahb->getAndroidFormat();
}

void EmulatedANativeWindowHelper::setSwapInterval(EGLNativeWindowType window, int interval) {
    ALOGE("Unimplemented");
    (void)window;
    (void)interval;
}

int EmulatedANativeWindowHelper::queueBuffer(EGLNativeWindowType window, EGLClientBuffer buffer,
                                             int fence) {
    auto anw = reinterpret_cast<EmulatedANativeWindow*>(window);
    return anw->queueBuffer(buffer, fence);
}

int EmulatedANativeWindowHelper::dequeueBuffer(EGLNativeWindowType window, EGLClientBuffer* buffer,
                                               int* fence) {
    auto anw = reinterpret_cast<EmulatedANativeWindow*>(window);
    return anw->dequeueBuffer(buffer, fence);
}

int EmulatedANativeWindowHelper::cancelBuffer(EGLNativeWindowType window, EGLClientBuffer buffer) {
    auto anw = reinterpret_cast<EmulatedANativeWindow*>(window);
    return anw->cancelBuffer(buffer);
}

int EmulatedANativeWindowHelper::getHostHandle(EGLClientBuffer buffer, Gralloc*) {
    auto ahb = reinterpret_cast<EmulatedAHardwareBuffer*>(buffer);
    return ahb->getResourceId();
}

EGLNativeWindowType EmulatedANativeWindowHelper::createNativeWindowForTesting(Gralloc* gralloc,
                                                                              uint32_t width,
                                                                              uint32_t height) {
    std::vector<std::unique_ptr<EmulatedAHardwareBuffer>> buffers;
    for (int i = 0; i < 3; i++) {
        AHardwareBuffer* ahb = nullptr;
        if (gralloc->allocate(width, height, DRM_FORMAT_ABGR8888, -1, &ahb) != 0) {
            ALOGE("Failed to allocate gralloc buffer.");
            return nullptr;
        }
        buffers.emplace_back(reinterpret_cast<EmulatedAHardwareBuffer*>(ahb));
    }
    return reinterpret_cast<EGLNativeWindowType>(
        new EmulatedANativeWindow(width, height, DRM_FORMAT_ABGR8888, std::move(buffers)));
}

ANativeWindowHelper* createPlatformANativeWindowHelper() {
    return new EmulatedANativeWindowHelper();
}

}  // namespace gfxstream
