/*
 * Copyright (C) 2016 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 "HalCamera.h"
#include "VirtualCamera.h"
#include "Enumerator.h"

#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>


namespace android {
namespace automotive {
namespace evs {
namespace V1_0 {
namespace implementation {


// TODO:  We need to hook up death monitoring to detect stream death so we can attempt a reconnect


sp<VirtualCamera> HalCamera::makeVirtualCamera() {

    // Create the client camera interface object
    sp<VirtualCamera> client = new VirtualCamera(this);
    if (client == nullptr) {
        ALOGE("Failed to create client camera object");
        return nullptr;
    }

    // Make sure we have enough buffers available for all our clients
    if (!changeFramesInFlight(client->getAllowedBuffers())) {
        // Gah!  We couldn't get enough buffers, so we can't support this client
        // Null the pointer, dropping our reference, thus destroying the client object
        client = nullptr;
        return nullptr;
    }

    // Add this client to our ownership list via weak pointer
    mClients.push_back(client);

    // Return the strong pointer to the client
    return client;
}


void HalCamera::disownVirtualCamera(sp<VirtualCamera> virtualCamera) {
    // Ignore calls with null pointers
    if (virtualCamera.get() == nullptr) {
        ALOGW("Ignoring disownVirtualCamera call with null pointer");
        return;
    }

    // Make sure the virtual camera's stream is stopped
    virtualCamera->stopVideoStream();

    // Remove the virtual camera from our client list
    unsigned clientCount = mClients.size();
    mClients.remove(virtualCamera);
    if (clientCount != mClients.size() + 1) {
        ALOGE("Couldn't find camera in our client list to remove it");
    }
    virtualCamera->shutdown();

    // Recompute the number of buffers required with the target camera removed from the list
    if (!changeFramesInFlight(0)) {
        ALOGE("Error when trying to reduce the in flight buffer count");
    }
}


bool HalCamera::changeFramesInFlight(int delta) {
    // Walk all our clients and count their currently required frames
    unsigned bufferCount = 0;
    for (auto&& client :  mClients) {
        sp<VirtualCamera> virtCam = client.promote();
        if (virtCam != nullptr) {
            bufferCount += virtCam->getAllowedBuffers();
        }
    }

    // Add the requested delta
    bufferCount += delta;

    // Never drop below 1 buffer -- even if all client cameras get closed
    if (bufferCount < 1) {
        bufferCount = 1;
    }

    // Ask the hardware for the resulting buffer count
    Return<EvsResult> result = mHwCamera->setMaxFramesInFlight(bufferCount);
    bool success = (result.isOk() && result == EvsResult::OK);

    // Update the size of our array of outstanding frame records
    if (success) {
        std::vector<FrameRecord> newRecords;
        newRecords.reserve(bufferCount);

        // Copy and compact the old records that are still active
        for (const auto& rec : mFrames) {
            if (rec.refCount > 0) {
                newRecords.emplace_back(rec);
            }
        }
        if (newRecords.size() > (unsigned)bufferCount) {
            ALOGW("We found more frames in use than requested.");
        }

        mFrames.swap(newRecords);
    }

    return success;
}


Return<EvsResult> HalCamera::clientStreamStarting() {
    Return<EvsResult> result = EvsResult::OK;

    if (mStreamState == STOPPED) {
        mStreamState = RUNNING;
        result = mHwCamera->startVideoStream(this);
    }

    return result;
}


void HalCamera::clientStreamEnding() {
    // Do we still have a running client?
    bool stillRunning = false;
    for (auto&& client : mClients) {
        sp<VirtualCamera> virtCam = client.promote();
        if (virtCam != nullptr) {
            stillRunning |= virtCam->isStreaming();
        }
    }

    // If not, then stop the hardware stream
    if (!stillRunning) {
        mStreamState = STOPPED;
        mHwCamera->stopVideoStream();
    }
}


Return<void> HalCamera::doneWithFrame(const BufferDesc& buffer) {
    // Find this frame in our list of outstanding frames
    unsigned i;
    for (i=0; i<mFrames.size(); i++) {
        if (mFrames[i].frameId == buffer.bufferId) {
            break;
        }
    }
    if (i == mFrames.size()) {
        ALOGE("We got a frame back with an ID we don't recognize!");
    } else {
        // Are there still clients using this buffer?
        mFrames[i].refCount--;
        if (mFrames[i].refCount <= 0) {
            // Since all our clients are done with this buffer, return it to the device layer
            mHwCamera->doneWithFrame(buffer);
        }
    }

    return Void();
}


Return<void> HalCamera::deliverFrame(const BufferDesc& buffer) {
    // Run through all our clients and deliver this frame to any who are eligible
    unsigned frameDeliveries = 0;
    for (auto&& client : mClients) {
        sp<VirtualCamera> virtCam = client.promote();
        if (virtCam != nullptr) {
            if (virtCam->deliverFrame(buffer)) {
                frameDeliveries++;
            }
        }
    }

    if (frameDeliveries < 1) {
        // If none of our clients could accept the frame, then return it right away
        ALOGI("Trivially rejecting frame with no acceptances");
        mHwCamera->doneWithFrame(buffer);
    } else {
        // Add an entry for this frame in our tracking list
        unsigned i;
        for (i=0; i<mFrames.size(); i++) {
            if (mFrames[i].refCount == 0) {
                break;
            }
        }
        if (i == mFrames.size()) {
            mFrames.emplace_back(buffer.bufferId);
        } else {
            mFrames[i].frameId = buffer.bufferId;
        }
        mFrames[i].refCount = frameDeliveries;
    }

    return Void();
}

} // namespace implementation
} // namespace V1_0
} // namespace evs
} // namespace automotive
} // namespace android
