/*
 * Copyright (C) 2013 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "RingBufferConsumer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include <inttypes.h>

#include <utils/Log.h>

#include <gui/RingBufferConsumer.h>

#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
#define BI_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)

#undef assert
#define assert(x) ALOG_ASSERT((x), #x)

typedef android::RingBufferConsumer::PinnedBufferItem PinnedBufferItem;

namespace android {

RingBufferConsumer::RingBufferConsumer(const sp<IGraphicBufferConsumer>& consumer,
        uint32_t consumerUsage,
        int bufferCount) :
    ConsumerBase(consumer),
    mBufferCount(bufferCount),
    mLatestTimestamp(0)
{
    mConsumer->setConsumerUsageBits(consumerUsage);
    mConsumer->setMaxAcquiredBufferCount(bufferCount);

    assert(bufferCount > 0);
}

RingBufferConsumer::~RingBufferConsumer() {
}

void RingBufferConsumer::setName(const String8& name) {
    Mutex::Autolock _l(mMutex);
    mName = name;
    mConsumer->setConsumerName(name);
}

sp<PinnedBufferItem> RingBufferConsumer::pinSelectedBuffer(
        const RingBufferComparator& filter,
        bool waitForFence) {

    sp<PinnedBufferItem> pinnedBuffer;

    {
        List<RingBufferItem>::iterator it, end, accIt;
        BufferInfo acc, cur;
        BufferInfo* accPtr = NULL;

        Mutex::Autolock _l(mMutex);

        for (it = mBufferItemList.begin(), end = mBufferItemList.end();
             it != end;
             ++it) {

            const RingBufferItem& item = *it;

            cur.mCrop = item.mCrop;
            cur.mTransform = item.mTransform;
            cur.mScalingMode = item.mScalingMode;
            cur.mTimestamp = item.mTimestamp;
            cur.mFrameNumber = item.mFrameNumber;
            cur.mPinned = item.mPinCount > 0;

            int ret = filter.compare(accPtr, &cur);

            if (ret == 0) {
                accPtr = NULL;
            } else if (ret > 0) {
                acc = cur;
                accPtr = &acc;
                accIt = it;
            } // else acc = acc
        }

        if (!accPtr) {
            return NULL;
        }

        pinnedBuffer = new PinnedBufferItem(this, *accIt);
        pinBufferLocked(pinnedBuffer->getBufferItem());

    } // end scope of mMutex autolock

    if (waitForFence) {
        status_t err = pinnedBuffer->getBufferItem().mFence->waitForever(
                "RingBufferConsumer::pinSelectedBuffer");
        if (err != OK) {
            BI_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
                    strerror(-err), err);
        }
    }

    return pinnedBuffer;
}

status_t RingBufferConsumer::clear() {

    status_t err;
    Mutex::Autolock _l(mMutex);

    BI_LOGV("%s", __FUNCTION__);

    // Avoid annoying log warnings by returning early
    if (mBufferItemList.size() == 0) {
        return OK;
    }

    do {
        size_t pinnedFrames = 0;
        err = releaseOldestBufferLocked(&pinnedFrames);

        if (err == NO_BUFFER_AVAILABLE) {
            assert(pinnedFrames == mBufferItemList.size());
            break;
        }

        if (err == NOT_ENOUGH_DATA) {
            // Fine. Empty buffer item list.
            break;
        }

        if (err != OK) {
            BI_LOGE("Clear failed, could not release buffer");
            return err;
        }

    } while(true);

    return OK;
}

nsecs_t RingBufferConsumer::getLatestTimestamp() {
    Mutex::Autolock _l(mMutex);
    if (mBufferItemList.size() == 0) {
        return 0;
    }
    return mLatestTimestamp;
}

void RingBufferConsumer::pinBufferLocked(const BufferItem& item) {
    List<RingBufferItem>::iterator it, end;

    for (it = mBufferItemList.begin(), end = mBufferItemList.end();
         it != end;
         ++it) {

        RingBufferItem& find = *it;
        if (item.mGraphicBuffer == find.mGraphicBuffer) {
            find.mPinCount++;
            break;
        }
    }

    if (it == end) {
        BI_LOGE("Failed to pin buffer (timestamp %" PRId64 ", framenumber %" PRIu64 ")",
                 item.mTimestamp, item.mFrameNumber);
    } else {
        BI_LOGV("Pinned buffer (frame %" PRIu64 ", timestamp %" PRId64 ")",
                item.mFrameNumber, item.mTimestamp);
    }
}

status_t RingBufferConsumer::releaseOldestBufferLocked(size_t* pinnedFrames) {
    status_t err = OK;

    List<RingBufferItem>::iterator it, end, accIt;

    it = mBufferItemList.begin();
    end = mBufferItemList.end();
    accIt = end;

    if (it == end) {
        /**
         * This is fine. We really care about being able to acquire a buffer
         * successfully after this function completes, not about it releasing
         * some buffer.
         */
        BI_LOGV("%s: No buffers yet acquired, can't release anything",
              __FUNCTION__);
        return NOT_ENOUGH_DATA;
    }

    for (; it != end; ++it) {
        RingBufferItem& find = *it;

        if (find.mPinCount > 0) {
            if (pinnedFrames != NULL) {
                ++(*pinnedFrames);
            }
            // Filter out pinned frame when searching for buffer to release
            continue;
        }

        if (find.mTimestamp < accIt->mTimestamp || accIt == end) {
            accIt = it;
        }
    }

    if (accIt != end) {
        RingBufferItem& item = *accIt;

        // In case the object was never pinned, pass the acquire fence
        // back to the release fence. If the fence was already waited on,
        // it'll just be a no-op to wait on it again.

        // item.mGraphicBuffer was populated with the proper graphic-buffer
        // at acquire even if it was previously acquired
        err = addReleaseFenceLocked(item.mBuf,
                item.mGraphicBuffer, item.mFence);

        if (err != OK) {
            BI_LOGE("Failed to add release fence to buffer "
                    "(timestamp %" PRId64 ", framenumber %" PRIu64,
                    item.mTimestamp, item.mFrameNumber);
            return err;
        }

        BI_LOGV("Attempting to release buffer timestamp %" PRId64 ", frame %" PRIu64,
                item.mTimestamp, item.mFrameNumber);

        // item.mGraphicBuffer was populated with the proper graphic-buffer
        // at acquire even if it was previously acquired
        err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer,
                                  EGL_NO_DISPLAY,
                                  EGL_NO_SYNC_KHR);
        if (err != OK) {
            BI_LOGE("Failed to release buffer: %s (%d)",
                    strerror(-err), err);
            return err;
        }

        BI_LOGV("Buffer timestamp %" PRId64 ", frame %" PRIu64 " evicted",
                item.mTimestamp, item.mFrameNumber);

        size_t currentSize = mBufferItemList.size();
        mBufferItemList.erase(accIt);
        assert(mBufferItemList.size() == currentSize - 1);
    } else {
        BI_LOGW("All buffers pinned, could not find any to release");
        return NO_BUFFER_AVAILABLE;

    }

    return OK;
}

void RingBufferConsumer::onFrameAvailable(const BufferItem& item) {
    status_t err;

    {
        Mutex::Autolock _l(mMutex);

        /**
         * Release oldest frame
         */
        if (mBufferItemList.size() >= (size_t)mBufferCount) {
            err = releaseOldestBufferLocked(/*pinnedFrames*/NULL);
            assert(err != NOT_ENOUGH_DATA);

            // TODO: implement the case for NO_BUFFER_AVAILABLE
            assert(err != NO_BUFFER_AVAILABLE);
            if (err != OK) {
                return;
            }
            // TODO: in unpinBuffer rerun this routine if we had buffers
            // we could've locked but didn't because there was no space
        }

        RingBufferItem& item = *mBufferItemList.insert(mBufferItemList.end(),
                                                       RingBufferItem());

        /**
         * Acquire new frame
         */
        err = acquireBufferLocked(&item, 0);
        if (err != OK) {
            if (err != NO_BUFFER_AVAILABLE) {
                BI_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
            }

            mBufferItemList.erase(--mBufferItemList.end());
            return;
        }

        BI_LOGV("New buffer acquired (timestamp %" PRId64 "), "
                "buffer items %zu out of %d",
                item.mTimestamp,
                mBufferItemList.size(), mBufferCount);

        if (item.mTimestamp < mLatestTimestamp) {
            BI_LOGE("Timestamp  decreases from %" PRId64 " to %" PRId64,
                    mLatestTimestamp, item.mTimestamp);
        }

        mLatestTimestamp = item.mTimestamp;

        item.mGraphicBuffer = mSlots[item.mBuf].mGraphicBuffer;
    } // end of mMutex lock

    ConsumerBase::onFrameAvailable(item);
}

void RingBufferConsumer::unpinBuffer(const BufferItem& item) {
    Mutex::Autolock _l(mMutex);

    List<RingBufferItem>::iterator it, end, accIt;

    for (it = mBufferItemList.begin(), end = mBufferItemList.end();
         it != end;
         ++it) {

        RingBufferItem& find = *it;
        if (item.mGraphicBuffer == find.mGraphicBuffer) {
            status_t res = addReleaseFenceLocked(item.mBuf,
                    item.mGraphicBuffer, item.mFence);

            if (res != OK) {
                BI_LOGE("Failed to add release fence to buffer "
                        "(timestamp %" PRId64 ", framenumber %" PRIu64,
                        item.mTimestamp, item.mFrameNumber);
                return;
            }

            find.mPinCount--;
            break;
        }
    }

    if (it == end) {
        // This should never happen. If it happens, we have a bug.
        BI_LOGE("Failed to unpin buffer (timestamp %" PRId64 ", framenumber %" PRIu64 ")",
                 item.mTimestamp, item.mFrameNumber);
    } else {
        BI_LOGV("Unpinned buffer (timestamp %" PRId64 ", framenumber %" PRIu64 ")",
                 item.mTimestamp, item.mFrameNumber);
    }
}

status_t RingBufferConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) {
    Mutex::Autolock _l(mMutex);
    return mConsumer->setDefaultBufferSize(w, h);
}

status_t RingBufferConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
    Mutex::Autolock _l(mMutex);
    return mConsumer->setDefaultBufferFormat(defaultFormat);
}

status_t RingBufferConsumer::setConsumerUsage(uint32_t usage) {
    Mutex::Autolock _l(mMutex);
    return mConsumer->setConsumerUsageBits(usage);
}

} // namespace android
