/*
**
** Copyright 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 "CameraRequest"
#include <utils/Log.h>
#include <utils/String16.h>

#include <camera/camera2/CaptureRequest.h>
#include <camera/StringUtils.h>

#include <binder/Parcel.h>
#include <gui/Surface.h>
#include <gui/view/Surface.h>

namespace android {
namespace hardware {
namespace camera2 {

// These must be in the .cpp (to avoid inlining)
CaptureRequest::CaptureRequest() = default;
CaptureRequest::~CaptureRequest() = default;
CaptureRequest::CaptureRequest(const CaptureRequest& rhs) = default;
CaptureRequest::CaptureRequest(CaptureRequest&& rhs) noexcept = default;


status_t CaptureRequest::readFromParcel(const android::Parcel* parcel) {
    if (parcel == NULL) {
        ALOGE("%s: Null parcel", __FUNCTION__);
        return BAD_VALUE;
    }

    mSurfaceList.clear();
    mStreamIdxList.clear();
    mSurfaceIdxList.clear();
    mPhysicalCameraSettings.clear();

    status_t err = OK;

    int32_t settingsCount;
    if ((err = parcel->readInt32(&settingsCount)) != OK) {
        ALOGE("%s: Failed to read the settings count from parcel: %d", __FUNCTION__, err);
        return err;
    }

    if (settingsCount <= 0) {
        ALOGE("%s: Settings count %d should always be positive!", __FUNCTION__, settingsCount);
        return BAD_VALUE;
    }

    for (int32_t i = 0; i < settingsCount; i++) {
        String16 id;
        if ((err = parcel->readString16(&id)) != OK) {
            ALOGE("%s: Failed to read camera id!", __FUNCTION__);
            return BAD_VALUE;
        }

        CameraMetadata settings;
        if ((err = settings.readFromParcel(parcel)) != OK) {
            ALOGE("%s: Failed to read metadata from parcel", __FUNCTION__);
            return err;
        }
        ALOGV("%s: Read metadata from parcel", __FUNCTION__);
        mPhysicalCameraSettings.push_back({toStdString(id), settings});
    }

    int isReprocess = 0;
    if ((err = parcel->readInt32(&isReprocess)) != OK) {
        ALOGE("%s: Failed to read reprocessing from parcel", __FUNCTION__);
        return err;
    }
    mIsReprocess = (isReprocess != 0);

    int32_t size;
    if ((err = parcel->readInt32(&size)) != OK) {
        ALOGE("%s: Failed to read surface list size from parcel", __FUNCTION__);
        return err;
    }
    ALOGV("%s: Read surface list size = %d", __FUNCTION__, size);

    // Do not distinguish null arrays from 0-sized arrays.
    for (int32_t i = 0; i < size; ++i) {
        // Parcel.writeParcelableArray
        std::optional<std::string> className;
        parcel->readUtf8FromUtf16(&className);
        ALOGV("%s: Read surface class = %s", __FUNCTION__,
              className.value_or("<null>").c_str());

        if (className == std::nullopt) {
            continue;
        }

        // Surface.writeToParcel
        view::Surface surfaceShim;
        if ((err = surfaceShim.readFromParcel(parcel)) != OK) {
            ALOGE("%s: Failed to read output target Surface %d from parcel: %s (%d)",
                    __FUNCTION__, i, strerror(-err), err);
            return err;
        }

        sp<Surface> surface;
        if (surfaceShim.graphicBufferProducer != NULL) {
            surface = new Surface(surfaceShim.graphicBufferProducer);
        }

        mSurfaceList.push_back(surface);
    }

    int32_t streamSurfaceSize;
    if ((err = parcel->readInt32(&streamSurfaceSize)) != OK) {
        ALOGE("%s: Failed to read streamSurfaceSize from parcel", __FUNCTION__);
        return err;
    }

    if (streamSurfaceSize < 0) {
        ALOGE("%s: Bad streamSurfaceSize %d from parcel", __FUNCTION__, streamSurfaceSize);
        return BAD_VALUE;
    }

    for (int32_t i = 0; i < streamSurfaceSize; ++i) {
        int streamIdx;
        if ((err = parcel->readInt32(&streamIdx)) != OK) {
            ALOGE("%s: Failed to read stream index from parcel", __FUNCTION__);
            return err;
        }
        mStreamIdxList.push_back(streamIdx);

        int surfaceIdx;
        if ((err = parcel->readInt32(&surfaceIdx)) != OK) {
            ALOGE("%s: Failed to read surface index from parcel", __FUNCTION__);
            return err;
        }
        mSurfaceIdxList.push_back(surfaceIdx);
    }

    int32_t hasUserTag;
    if ((err = parcel->readInt32(&hasUserTag)) != OK) {
        ALOGE("%s: Failed to read user tag availability flag", __FUNCTION__);
        return BAD_VALUE;
    }
    if (hasUserTag) {
        String16 userTag;
        if ((err = parcel->readString16(&userTag)) != OK) {
            ALOGE("%s: Failed to read user tag!", __FUNCTION__);
            return BAD_VALUE;
        }
        mUserTag = toStdString(userTag);
    }

    return OK;
}

status_t CaptureRequest::writeToParcel(android::Parcel* parcel) const {
    if (parcel == NULL) {
        ALOGE("%s: Null parcel", __FUNCTION__);
        return BAD_VALUE;
    }

    status_t err = OK;

    int32_t settingsCount = static_cast<int32_t>(mPhysicalCameraSettings.size());

    if ((err = parcel->writeInt32(settingsCount)) != OK) {
        ALOGE("%s: Failed to write settings count!", __FUNCTION__);
        return err;
    }

    for (const auto &it : mPhysicalCameraSettings) {
        if ((err = parcel->writeString16(toString16(it.id))) != OK) {
            ALOGE("%s: Failed to camera id!", __FUNCTION__);
            return err;
        }

        if ((err = it.settings.writeToParcel(parcel)) != OK) {
            ALOGE("%s: Failed to write settings!", __FUNCTION__);
            return err;
        }
    }

    parcel->writeInt32(mIsReprocess ? 1 : 0);

    if (mSurfaceConverted) {
        parcel->writeInt32(0); // 0-sized array
    } else {
        int32_t size = static_cast<int32_t>(mSurfaceList.size());

        // Send 0-sized arrays when it's empty. Do not send null arrays.
        parcel->writeInt32(size);

        for (int32_t i = 0; i < size; ++i) {
            // not sure if readParcelableArray does this, hard to tell from source
            parcel->writeString16(String16("android.view.Surface"));

            // Surface.writeToParcel
            view::Surface surfaceShim;
            surfaceShim.name = String16("unknown_name");
            surfaceShim.graphicBufferProducer = mSurfaceList[i]->getIGraphicBufferProducer();
            if ((err = surfaceShim.writeToParcel(parcel)) != OK) {
                ALOGE("%s: Failed to write output target Surface %d to parcel: %s (%d)",
                        __FUNCTION__, i, strerror(-err), err);
                return err;
            }
        }
    }

    parcel->writeInt32(mStreamIdxList.size());
    for (size_t i = 0; i < mStreamIdxList.size(); ++i) {
        if ((err = parcel->writeInt32(mStreamIdxList[i])) != OK) {
            ALOGE("%s: Failed to write stream index to parcel", __FUNCTION__);
            return err;
        }
        if ((err = parcel->writeInt32(mSurfaceIdxList[i])) != OK) {
            ALOGE("%s: Failed to write surface index to parcel", __FUNCTION__);
            return err;
        }
    }

    if (mUserTag.empty()) {
        parcel->writeInt32(0);
    } else {
        parcel->writeInt32(1);
        parcel->writeString16(toString16(mUserTag));
    }

    return OK;
}

} // namespace camera2
} // namespace hardware
} // namespace android
