/*
 * Copyright (C) 2009 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 "Metadata"
#include <utils/Log.h>

#include <sys/types.h>
#include <media/Metadata.h>
#include <binder/Parcel.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>

// This file contains code to serialize Metadata triples (key, type,
// value) into a parcel. The Parcel is destinated to be decoded by the
// Metadata.java class.

namespace {
// All these constants below must be kept in sync with Metadata.java.
enum MetadataId {
    FIRST_SYSTEM_ID = 1,
    LAST_SYSTEM_ID = 31,
    FIRST_CUSTOM_ID = 8192
};

// Types
enum Types {
    STRING_VAL = 1,
    INTEGER_VAL,
    BOOLEAN_VAL,
    LONG_VAL,
    DOUBLE_VAL,
    DATE_VAL,
    BYTE_ARRAY_VAL,
};

const size_t kRecordHeaderSize = 3 * sizeof(int32_t);
const int32_t kMetaMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'

}  // anonymous namespace

namespace android {
namespace media {

Metadata::Metadata(Parcel *p)
    :mData(p),
     mBegin(p->dataPosition()) { }

Metadata::~Metadata() { }

void Metadata::resetParcel()
{
    mData->setDataPosition(mBegin);
}

// Update the 4 bytes int at the beginning of the parcel which holds
// the number of bytes written so far.
void Metadata::updateLength()
{
    const size_t end = mData->dataPosition();

    mData->setDataPosition(mBegin);
    mData->writeInt32(end - mBegin);
    mData->setDataPosition(end);
}

// Write the header. The java layer will look for the marker.
bool Metadata::appendHeader()
{
    bool ok = true;

    // Placeholder for the length of the metadata
    ok = ok && mData->writeInt32(-1) == OK;
    ok = ok && mData->writeInt32(kMetaMarker) == OK;
    return ok;
}

bool Metadata::appendBool(int key, bool val)
{
    if (!checkKey(key)) {
        return false;
    }

    const size_t begin = mData->dataPosition();
    bool ok = true;

    // 4 int32s: size, key, type, value.
    ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
    ok = ok && mData->writeInt32(key) == OK;
    ok = ok && mData->writeInt32(BOOLEAN_VAL) == OK;
    ok = ok && mData->writeInt32(val ? 1 : 0) == OK;
    if (!ok) {
        mData->setDataPosition(begin);
    }
    return ok;
}

bool Metadata::appendInt32(int key, int32_t val)
{
    if (!checkKey(key)) {
        return false;
    }

    const size_t begin = mData->dataPosition();
    bool ok = true;

    // 4 int32s: size, key, type, value.
    ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
    ok = ok && mData->writeInt32(key) == OK;
    ok = ok && mData->writeInt32(INTEGER_VAL) == OK;
    ok = ok && mData->writeInt32(val) == OK;
    if (!ok) {
        mData->setDataPosition(begin);
    }
    return ok;
}

// Check the key (i.e metadata id) is valid if it is a system one.
// Loop over all the exiting ones in the Parcel to check for duplicate
// (not allowed).
bool Metadata::checkKey(int key)
{
    if (key < FIRST_SYSTEM_ID ||
        (LAST_SYSTEM_ID < key && key < FIRST_CUSTOM_ID)) {
        LOGE("Bad key %d", key);
        return false;
    }
    size_t curr = mData->dataPosition();
    // Loop over the keys to check if it has been used already.
    mData->setDataPosition(mBegin);

    bool error = false;
    size_t left = curr - mBegin;
    while (left > 0) {
        size_t pos = mData->dataPosition();
        size_t size = mData->readInt32();
        if (size < kRecordHeaderSize || size > left) {
            error = true;
            break;
        }
        if (mData->readInt32() == key) {
            LOGE("Key exists already %d", key);
            error = true;
            break;
        }
        mData->setDataPosition(pos + size);
        left -= size;
    }
    mData->setDataPosition(curr);
    return !error;
}

}  // namespace android::media
}  // namespace android
