/*
 * Copyright 2014 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.
 */

#ifndef IMG_UTILS_TIFF_ENTRY_IMPL
#define IMG_UTILS_TIFF_ENTRY_IMPL

#include <img_utils/TiffIfd.h>
#include <img_utils/TiffEntry.h>
#include <img_utils/TiffHelpers.h>
#include <img_utils/Output.h>
#include <img_utils/EndianUtils.h>

#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
#include <utils/StrongPointer.h>
#include <stdint.h>

namespace android {
namespace img_utils {

template<typename T>
class TiffEntryImpl : public TiffEntry {
    public:
        TiffEntryImpl(uint16_t tag, TagType type, uint32_t count, Endianness end, const T* data);
        virtual ~TiffEntryImpl();

        status_t writeData(uint32_t offset, /*out*/EndianOutput* out) const;
        status_t writeTagInfo(uint32_t offset, /*out*/EndianOutput* out) const;

        uint32_t getCount() const;
        uint16_t getTag() const;
        TagType getType() const;
        Endianness getEndianness() const;
        size_t getSize() const;
        uint32_t getComparableValue() const;

    protected:
        const void* getDataHelper() const;
        uint32_t getActualSize() const;

        uint16_t mTag;
        uint16_t mType;
        uint32_t mCount;
        Endianness mEnd;
        Vector<T> mData;

};

template<typename T>
TiffEntryImpl<T>::TiffEntryImpl(uint16_t tag, TagType type, uint32_t count, Endianness end,
        const T* data)
        : mTag(tag), mType(static_cast<uint16_t>(type)), mCount(count), mEnd(end) {
    count = (type == RATIONAL || type == SRATIONAL) ? count * 2 : count;
    ssize_t index = mData.appendArray(data, count);
    LOG_ALWAYS_FATAL_IF(index < 0, "%s: Could not allocate vector for data.", __FUNCTION__);
}

template<typename T>
TiffEntryImpl<T>::~TiffEntryImpl() {}

template<typename T>
uint32_t TiffEntryImpl<T>::getCount() const {
    return mCount;
}

template<typename T>
uint16_t TiffEntryImpl<T>::getTag() const {
    return mTag;
}

template<typename T>
TagType TiffEntryImpl<T>::getType() const {
    return static_cast<TagType>(mType);
}

template<typename T>
const void* TiffEntryImpl<T>::getDataHelper() const {
    return reinterpret_cast<const void*>(mData.array());
}

template<typename T>
size_t TiffEntryImpl<T>::getSize() const {
    uint32_t total = getActualSize();
    WORD_ALIGN(total)
    return (total <= OFFSET_SIZE) ? 0 : total;
}

template<typename T>
uint32_t TiffEntryImpl<T>::getActualSize() const {
    uint32_t total = sizeof(T) * mCount;
    if (getType() == RATIONAL || getType() == SRATIONAL) {
        // 2 ints stored for each rational, multiply by 2
        total <<= 1;
    }
    return total;
}

template<typename T>
Endianness TiffEntryImpl<T>::getEndianness() const {
    return mEnd;
}

template<typename T>
uint32_t TiffEntryImpl<T>::getComparableValue() const {
    return mTag;
}

template<typename T>
status_t TiffEntryImpl<T>::writeTagInfo(uint32_t offset, /*out*/EndianOutput* out) const {
    assert((offset % TIFF_WORD_SIZE) == 0);
    status_t ret = OK;
    BAIL_ON_FAIL(out->write(&mTag, 0, 1), ret);
    BAIL_ON_FAIL(out->write(&mType, 0, 1), ret);
    BAIL_ON_FAIL(out->write(&mCount, 0, 1), ret);

    uint32_t dataSize = getActualSize();
    if (dataSize > OFFSET_SIZE) {
        BAIL_ON_FAIL(out->write(&offset, 0, 1), ret);
    } else {
        uint32_t count = mCount;
        if (getType() == RATIONAL || getType() == SRATIONAL) {
            /**
             * Rationals are stored as an array of ints.  Each
             * rational is represented by 2 ints.  To recover the
             * size of the array here, multiply the count by 2.
             */
            count <<= 1;
        }
        BAIL_ON_FAIL(out->write(mData.array(), 0, count), ret);
        ZERO_TILL_WORD(out, dataSize, ret);
    }
    return ret;
}

template<typename T>
status_t TiffEntryImpl<T>::writeData(uint32_t offset, EndianOutput* out) const {
    status_t ret = OK;

    // Some tags have fixed-endian value output
    Endianness tmp = UNDEFINED_ENDIAN;
    if (mEnd != UNDEFINED_ENDIAN) {
        tmp = out->getEndianness();
        out->setEndianness(mEnd);
    }

    uint32_t count = mCount;
    if (getType() == RATIONAL || getType() == SRATIONAL) {
        /**
         * Rationals are stored as an array of ints.  Each
         * rational is represented by 2 ints.  To recover the
         * size of the array here, multiply the count by 2.
         */
        count <<= 1;
    }

    BAIL_ON_FAIL(out->write(mData.array(), 0, count), ret);

    if (mEnd != UNDEFINED_ENDIAN) {
        out->setEndianness(tmp);
    }

    // Write to next word alignment
    ZERO_TILL_WORD(out, sizeof(T) * count, ret);
    return ret;
}

template<>
inline status_t TiffEntryImpl<sp<TiffIfd> >::writeTagInfo(uint32_t offset,
        /*out*/EndianOutput* out) const {
    assert((offset % TIFF_WORD_SIZE) == 0);
    status_t ret = OK;
    BAIL_ON_FAIL(out->write(&mTag, 0, 1), ret);
    BAIL_ON_FAIL(out->write(&mType, 0, 1), ret);
    BAIL_ON_FAIL(out->write(&mCount, 0, 1), ret);

    BAIL_ON_FAIL(out->write(&offset, 0, 1), ret);
    return ret;
}

template<>
inline uint32_t TiffEntryImpl<sp<TiffIfd> >::getActualSize() const {
    uint32_t total = 0;
    for (size_t i = 0; i < mData.size(); ++i) {
        total += mData[i]->getSize();
    }
    return total;
}

template<>
inline status_t TiffEntryImpl<sp<TiffIfd> >::writeData(uint32_t offset, EndianOutput* out) const {
    status_t ret = OK;
    for (uint32_t i = 0; i < mCount; ++i) {
        BAIL_ON_FAIL(mData[i]->writeData(offset, out), ret);
        offset += mData[i]->getSize();
    }
    return ret;
}

} /*namespace img_utils*/
} /*namespace android*/

#endif /*IMG_UTILS_TIFF_ENTRY_IMPL*/


