/*
 * 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() {
    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();
}

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
