/*
 * Copyright (C) 2015-2020 Intel Corporation.
 *
 * 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.
 */

#define LOG_TAG "CameraBuffer"

#include <sys/mman.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <vector>

#include "iutils/CameraLog.h"
#include "iutils/Utils.h"

#include "PlatformData.h"
#include "CameraBuffer.h"

namespace icamera {
CameraBuffer::CameraBuffer(int cameraId, int usage, int memory, uint32_t size, int index, int format) :
    mNumPlanes(1),
    mAllocatedMemory(false),
    mU(nullptr),
    mBufferUsage(usage),
    mSettingSequence(-1)

{
    v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
    int num_plane = 1;

    LOG1("%s: construct CameraBuffer with cameraId:%d, usage:%d, memory:%d, size:%d, format:%d, index:%d",
         __func__, cameraId, usage, memory, size, format, index);

    mU = new camera_buffer_t;
    CLEAR(*mU);
    mU->flags = BUFFER_FLAG_INTERNAL;
    mU->sequence = -1;

    switch (usage) {
        case BUFFER_USAGE_PSYS_INPUT:
            //follow through
        case BUFFER_USAGE_PSYS_INTERNAL:
        case BUFFER_USAGE_GENERAL:
            if (PlatformData::isIsysEnabled(cameraId)
                && PlatformData::isCSIFrontEndCapture(cameraId)) {
                type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
                num_plane = CameraUtils::getNumOfPlanes(format);
            } else {
                type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
            }
            break;
        case BUFFER_USAGE_PSYS_STATS:
            type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
            break;
        case BUFFER_USAGE_MIPI_CAPTURE:
        case BUFFER_USAGE_METADATA:
            type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
            num_plane = CameraUtils::getNumOfPlanes(format);
            break;
        default:
            LOGE("Not supported Usage");
    }

    CLEAR(mMmapAddrs);
    CLEAR(mDmaFd);

    initBuffer(memory, type, size, index, num_plane);
}

CameraBuffer::~CameraBuffer()
{
    LOG1("Free CameraBuffer");

    freeMemory();

    if (mU->flags & BUFFER_FLAG_INTERNAL) {
        delete mU;
    }
}

void CameraBuffer::initBuffer(int memType, v4l2_buf_type bufType, uint32_t size, int idx, int num_plane)
{
    mV.SetMemory(memType);
    mV.SetIndex(idx);

    mV.SetType(bufType);

    if (!V4L2_TYPE_IS_MULTIPLANAR(bufType)) {
        mV.SetOffset(0, 0);
        mV.SetLength(size, 0);
        LOGE("SINGLE PLANE!");
    } else {
        mV.SetLength(num_plane, 0);
        mNumPlanes = num_plane;
        for (int i = 0; i < mNumPlanes; ++i) {
            mV.SetLength(size, i);
        }
    }

    mV.SetFlags(mV.Flags() | V4L2_BUF_FLAG_NO_CACHE_INVALIDATE | V4L2_BUF_FLAG_NO_CACHE_CLEAN);
}

//Helper function to construct a Internal CameraBuffer
std::shared_ptr<CameraBuffer> CameraBuffer::create(int cameraId, int usage, int memory, unsigned int size, int index,
                                              int srcFmt, int srcWidth, int srcHeight)
{
    std::shared_ptr<CameraBuffer> camBuffer = std::make_shared<CameraBuffer>(cameraId, usage, memory, size, index, srcFmt);

    CheckError(!camBuffer, nullptr, "@%s: fail to alloc CameraBuffer", __func__);

    camBuffer->setUserBufferInfo(srcFmt, srcWidth, srcHeight);

    int ret = camBuffer->allocateMemory();

    CheckError(ret != OK, nullptr, "Allocate memory failed ret %d", ret);

    return camBuffer;
}

//Internal frame Buffer
void CameraBuffer::setUserBufferInfo(int format, int width, int height)
{
    LOG1("%s: format:%d, width:%d, height:%d", __func__, format, width, height);
    mU->s.width = width;
    mU->s.height = height;
    mU->s.format = format;
    if (format != -1) {
        mU->s.stride = CameraUtils::getStride(format, width);
    }
}

void CameraBuffer::setUserBufferInfo(int format, int width, int height, void *usrPtr)
{
    setUserBufferInfo(format, width, height);
    setAddr(usrPtr, 0);
}

//Called when a buffer is from the application
void CameraBuffer::setUserBufferInfo(camera_buffer_t *ubuffer)
{
    CheckError(ubuffer == nullptr, VOID_VALUE, "%s: ubuffer is nullptr", __func__);

    if (mU->flags & BUFFER_FLAG_INTERNAL) delete mU;
    mU = ubuffer;

    LOG1("%s: ubuffer->s.MemType: %d, addr: %p, fd: %d", __func__, ubuffer->s.memType,
         ubuffer->addr, ubuffer->dmafd);
    //update the v4l2 buffer memory with user info
    switch (ubuffer->s.memType) {
        case V4L2_MEMORY_USERPTR:
            setAddr(ubuffer->addr, 0);
            break;
        case V4L2_MEMORY_DMABUF:
            setFd(ubuffer->dmafd, 0);
            break;
        case V4L2_MEMORY_MMAP:
            /* do nothing */
            break;
        default:
            LOGE("iomode %d is not supported yet.", mV.Memory());
            break;
    }

    if (mU->s.streamType == CAMERA_STREAM_INPUT || ubuffer->sequence >= 0) {
        // update timestamp if raw buffer is selected by user and timestamp is set
        if (ubuffer->timestamp > 0) {
            struct timeval timestamp = { 0 };
            timestamp.tv_sec = ubuffer->timestamp / 1000000000LL;
            timestamp.tv_usec = (ubuffer->timestamp - timestamp.tv_sec * 1000000000LL) / 1000LL;
            mV.SetTimestamp(timestamp);
        }
        mV.SetSequence(ubuffer->sequence);
        LOG2("%s, input buffer sequence %lld, timestamp %ld", __func__, ubuffer->sequence,
             ubuffer->timestamp);
    }
}

void CameraBuffer::updateV4l2Buffer(const v4l2_buffer_t& v4l2buf)
{
    mV.SetField(v4l2buf.field);
    mV.SetTimestamp(v4l2buf.timestamp);
    mV.SetSequence(v4l2buf.sequence);
    mV.SetRequestFd(v4l2buf.request_fd);
}

/*export mmap buffer as dma_buf fd stored in mV and mU*/
int CameraBuffer::exportMmapDmabuf(V4L2VideoNode *vDevice)
{
    std::vector<int> fds;

    int ret = vDevice->ExportFrame(mV.Index(), &fds);

    CheckError(ret != OK, -1, "exportMmapDmabuf failed, ret %d", ret);

    for (size_t i = 0; i < fds.size(); ++i) {
        setFd(fds[i], i);
    }

    if (mU->flags & BUFFER_FLAG_DMA_EXPORT) {
        mU->dmafd = getFd(0);
    }

    return OK;
}

int CameraBuffer::allocateMemory(V4L2VideoNode* vDevice)
{
    int ret = BAD_VALUE;
    LOG1("%s", __func__);
    switch(mV.Memory()) {
        case V4L2_MEMORY_USERPTR:
            ret = allocateUserPtr();
            mAllocatedMemory = true;
            mU->addr = getAddr();
            break;
        case V4L2_MEMORY_MMAP:
            exportMmapDmabuf(vDevice);
            ret = allocateMmap(vDevice);
            mU->addr = getAddr();
            mAllocatedMemory = true;
            break;
        default:
            LOGE("memory type %d is incorrect for allocateMemory.", mV.Memory());
            return BAD_VALUE;
    }

    return ret;
}

int CameraBuffer::allocateUserPtr()
{
    void* buffer = nullptr;
    for (int i = 0; i < mNumPlanes; ++i) {
        int ret = posix_memalign(&buffer, getpagesize(), mV.Length(i));
        CheckError(ret != 0, -1, "%s, posix_memalign fails, ret:%d", __func__, ret);
        mV.SetUserptr(reinterpret_cast<uintptr_t>(buffer), i);
        mMmapAddrs[i] = buffer;
    }
    return OK;
}

void CameraBuffer::freeUserPtr()
{
    for (int i = 0; i < mNumPlanes; ++i) {
        void* ptr = reinterpret_cast<void*>(mV.Userptr(i));
        mMmapAddrs[i] = nullptr;
        ::free(ptr);
        mV.SetUserptr(reinterpret_cast<uintptr_t>(nullptr), i);
    }
}

int CameraBuffer::allocateMmap(V4L2VideoNode* dev)
{
    std::vector<void*> addrs;
    int ret = dev->MapMemory(mV.Index(), PROT_READ | PROT_WRITE,
                            MAP_SHARED, &addrs);

    CheckError(ret != OK, -1, "allocateMmap failed, ret %d", ret);

    for (unsigned int i = 0; i < addrs.size(); ++i) {
        if (addrs[i] == MAP_FAILED) {
            mMmapAddrs[i] = nullptr;
            continue ;
        }
        mMmapAddrs[i] = addrs[i];
    }

    return OK;
}

void* CameraBuffer::getAddr(int plane)
{
    CheckError(plane < 0 || plane >= mNumPlanes, nullptr, "Wrong plane number %d", plane);

    switch (mV.Memory()) {
        case V4L2_MEMORY_MMAP:
            return mMmapAddrs[plane];
        case V4L2_MEMORY_USERPTR:
            return reinterpret_cast<void*>(mV.Userptr(plane));
        default:
            LOGE("%s: Not supported memory type %u", __func__, mV.Memory());
    }
    return nullptr;
}

void CameraBuffer::setAddr(void *addr, int plane)
{
    CheckError(plane < 0 || plane >= mNumPlanes, VOID_VALUE,
               "Wrong plane number %d", plane);

    switch (mV.Memory()) {
        case V4L2_MEMORY_MMAP:
            mMmapAddrs[plane] = addr;
            return;
        case V4L2_MEMORY_USERPTR:
            mV.SetUserptr(reinterpret_cast<uintptr_t>(addr), plane);
            mMmapAddrs[plane] = addr;
            return;
        default:
            LOGE("%s: Not supported memory type %u", __func__, mV.Memory());
    }
}

void CameraBuffer::freeMmap()
{
    int ret = OK;

    for (int i = 0; i < mNumPlanes; i++) {
        if (getFd(i) != -1) {
            ::close(getFd(i));
            setFd(-1, i);
        }
        if (mMmapAddrs[i]) {
            ret = ::munmap(mMmapAddrs[i], mV.Length(i));
            CheckError(ret != 0, VOID_VALUE, "failed to munmap buffer %d", i);
            mMmapAddrs[i] = nullptr;
        }
    }
}

void* CameraBuffer::mapDmaBufferAddr(int fd, unsigned int bufferSize)
{
    if(fd < 0 || !bufferSize) {
        LOGE("%s, fd:0x%x, bufferSize:%u", __func__, fd, bufferSize);
        return nullptr;
    }
    return ::mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
}

void CameraBuffer::unmapDmaBufferAddr(void* addr, unsigned int bufferSize)
{
    if(addr == nullptr || !bufferSize) {
        LOGE("%s, addr:%p, bufferSize:%u", __func__, addr, bufferSize);
        return;
    }
    munmap(addr, bufferSize);
}

void CameraBuffer::freeMemory()
{
    if (!mAllocatedMemory) {
        LOG2("@%s Memory(in %p) is not allocated by CameraBuffer class. Don't free it.", __func__, this);
        return ;
    }

    switch(mV.Memory()) {
        case V4L2_MEMORY_USERPTR:
            freeUserPtr();
            break;
        case V4L2_MEMORY_MMAP:
            freeMmap();
            break;
        default:
            LOGE("Free camera buffer failed, due to memory %d type is not implemented yet.", mV.Memory());
    }
}

void CameraBuffer::updateUserBuffer(void)
{
    mU->timestamp = TIMEVAL2NSECS(getTimestamp());
    mU->s.field = getField();

    // Use valid setting sequence to align shutter/parameter with buffer
    mU->sequence = (mSettingSequence < 0) ? getSequence() : mSettingSequence;
}

void CameraBuffer::updateFlags(void)
{
    int flag = V4L2_BUF_FLAG_NO_CACHE_INVALIDATE | V4L2_BUF_FLAG_NO_CACHE_CLEAN;
    bool set = true;

    //clear the flags if the buffers is accessed by the SW
    if ((mU->flags & BUFFER_FLAG_SW_READ) || (mU->flags & BUFFER_FLAG_SW_WRITE)) {
        set = false;
    }

    mV.SetFlags(set ? (mV.Flags() | flag): (mV.Flags() & (~flag)));
}

bool CameraBuffer::isFlagsSet(int flag)
{
    return ((mU->flags & flag) ? true : false);
}

void CameraBuffer::setFd(int val, int plane)
{
    if (mV.Memory() == V4L2_MEMORY_MMAP) {
        mDmaFd[plane] = val;
    } else {
        mV.SetFd(val, plane);
    }
}

int CameraBuffer::getFd(int plane)
{
    if (mV.Memory() == V4L2_MEMORY_MMAP) {
        return mDmaFd[plane];
    }

    return mV.Fd(plane);
}

}//namespace icamera
