/*
 * 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,
    TIMED_TEXT_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
