/*
 * Copyright 2015 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 <algorithm>
#include <memory.h>
#include <stdint.h>

#include "fifo/FifoControllerBase.h"
#include "fifo/FifoController.h"
#include "fifo/FifoControllerIndirect.h"
#include "fifo/FifoBuffer.h"

namespace oboe {

FifoBuffer::FifoBuffer(uint32_t bytesPerFrame, uint32_t capacityInFrames)
        : mBytesPerFrame(bytesPerFrame)
        , mStorage(nullptr)
        , mFramesReadCount(0)
        , mFramesUnderrunCount(0)
{
    mFifo = std::make_unique<FifoController>(capacityInFrames);
    // allocate buffer
    int32_t bytesPerBuffer = bytesPerFrame * capacityInFrames;
    mStorage = new uint8_t[bytesPerBuffer];
    mStorageOwned = true;
}

FifoBuffer::FifoBuffer( uint32_t  bytesPerFrame,
                        uint32_t  capacityInFrames,
                        std::atomic<uint64_t>  *readCounterAddress,
                        std::atomic<uint64_t>  *writeCounterAddress,
                        uint8_t  *dataStorageAddress
                        )
        : mBytesPerFrame(bytesPerFrame)
        , mStorage(dataStorageAddress)
        , mFramesReadCount(0)
        , mFramesUnderrunCount(0)
{
    mFifo = std::make_unique<FifoControllerIndirect>(capacityInFrames,
                                       readCounterAddress,
                                       writeCounterAddress);
    mStorage = dataStorageAddress;
    mStorageOwned = false;
}

FifoBuffer::~FifoBuffer() {
    if (mStorageOwned) {
        delete[] mStorage;
    }
}

int32_t FifoBuffer::convertFramesToBytes(int32_t frames) {
    return frames * mBytesPerFrame;
}

int32_t FifoBuffer::read(void *buffer, int32_t numFrames) {
    if (numFrames <= 0) {
        return 0;
    }
    // safe because numFrames is guaranteed positive
    uint32_t framesToRead = static_cast<uint32_t>(numFrames);
    uint32_t framesAvailable = mFifo->getFullFramesAvailable();
    framesToRead = std::min(framesToRead, framesAvailable);

    uint32_t readIndex = mFifo->getReadIndex(); // ranges 0 to capacity
    uint8_t *destination = reinterpret_cast<uint8_t *>(buffer);
    uint8_t *source = &mStorage[convertFramesToBytes(readIndex)];
    if ((readIndex + framesToRead) > mFifo->getFrameCapacity()) {
        // read in two parts, first part here is at the end of the mStorage buffer
        int32_t frames1 = static_cast<int32_t>(mFifo->getFrameCapacity() - readIndex);
        int32_t numBytes = convertFramesToBytes(frames1);
        if (numBytes < 0) {
            return static_cast<int32_t>(Result::ErrorOutOfRange);
        }
        memcpy(destination, source, static_cast<size_t>(numBytes));
        destination += numBytes;
        // read second part, which is at the beginning of mStorage
        source = &mStorage[0];
        int32_t frames2 = static_cast<uint32_t>(framesToRead - frames1);
        numBytes = convertFramesToBytes(frames2);
        if (numBytes < 0) {
            return static_cast<int32_t>(Result::ErrorOutOfRange);
        }
        memcpy(destination, source, static_cast<size_t>(numBytes));
    } else {
        // just read in one shot
        int32_t numBytes = convertFramesToBytes(framesToRead);
        if (numBytes < 0) {
            return static_cast<int32_t>(Result::ErrorOutOfRange);
        }
        memcpy(destination, source, static_cast<size_t>(numBytes));
    }
    mFifo->advanceReadIndex(framesToRead);

    return framesToRead;
}

int32_t FifoBuffer::write(const void *buffer, int32_t numFrames) {
    if (numFrames <= 0) {
        return 0;
    }
    // Guaranteed positive.
    uint32_t framesToWrite = static_cast<uint32_t>(numFrames);
    uint32_t framesAvailable = mFifo->getEmptyFramesAvailable();
    framesToWrite = std::min(framesToWrite, framesAvailable);

    uint32_t writeIndex = mFifo->getWriteIndex();
    int byteIndex = convertFramesToBytes(writeIndex);
    const uint8_t *source = reinterpret_cast<const uint8_t *>(buffer);
    uint8_t *destination = &mStorage[byteIndex];
    if ((writeIndex + framesToWrite) > mFifo->getFrameCapacity()) {
        // write in two parts, first part here
        int32_t frames1 = static_cast<uint32_t>(mFifo->getFrameCapacity() - writeIndex);
        int32_t numBytes = convertFramesToBytes(frames1);
        if (numBytes < 0) {
            return static_cast<int32_t>(Result::ErrorOutOfRange);
        }
        memcpy(destination, source, static_cast<size_t>(numBytes));
        // read second part
        source += convertFramesToBytes(frames1);
        destination = &mStorage[0];
        int frames2 = static_cast<uint32_t>(framesToWrite - frames1);
        numBytes = convertFramesToBytes(frames2);
        if (numBytes < 0) {
            return static_cast<int32_t>(Result::ErrorOutOfRange);
        }
        memcpy(destination, source, static_cast<size_t>(numBytes));
    } else {
        // just write in one shot
        int32_t numBytes = convertFramesToBytes(framesToWrite);
        if (numBytes < 0) {
            return static_cast<int32_t>(Result::ErrorOutOfRange);
        }
        memcpy(destination, source, static_cast<size_t>(numBytes));
    }
    mFifo->advanceWriteIndex(framesToWrite);

    return framesToWrite;
}

int32_t FifoBuffer::readNow(void *buffer, int32_t numFrames) {
    int32_t framesRead = read(buffer, numFrames);
    if (framesRead < 0) {
        return framesRead;
    }
    int32_t framesLeft = numFrames - framesRead;
    mFramesReadCount += framesRead;
    mFramesUnderrunCount += framesLeft;
    // Zero out any samples we could not set.
    if (framesLeft > 0) {
        uint8_t *destination = reinterpret_cast<uint8_t *>(buffer);
        destination += convertFramesToBytes(framesRead); // point to first byte not set
        int32_t bytesToZero = convertFramesToBytes(framesLeft);
        memset(destination, 0, static_cast<size_t>(bytesToZero));
    }

    return framesRead;
}


uint32_t FifoBuffer::getBufferCapacityInFrames() const {
    return mFifo->getFrameCapacity();
}

} // namespace oboe
