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

#define LOG_TAG "TiffWriter"

#include <img_utils/TiffHelpers.h>
#include <img_utils/TiffWriter.h>
#include <img_utils/TagDefinitions.h>

#include <assert.h>

namespace android {
namespace img_utils {

KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::buildTagMap(
            const TagDefinition_t* definitions, size_t length) {
    KeyedVector<uint16_t, const TagDefinition_t*> map;
    for(size_t i = 0; i < length; ++i) {
        map.add(definitions[i].tagId, definitions + i);
    }
    return map;
}

#define COMPARE(op) \
bool Orderable::operator op (const Orderable& orderable) const { \
    return getComparableValue() op orderable.getComparableValue(); \
}

#define ARRAY_SIZE(array) \
    (sizeof(array) / sizeof(array[0]))

KeyedVector<uint16_t, const TagDefinition_t*> TiffWriter::sTagMaps[] = {
    buildTagMap(TIFF_EP_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_EP_TAG_DEFINITIONS)),
    buildTagMap(DNG_TAG_DEFINITIONS, ARRAY_SIZE(DNG_TAG_DEFINITIONS)),
    buildTagMap(EXIF_2_3_TAG_DEFINITIONS, ARRAY_SIZE(EXIF_2_3_TAG_DEFINITIONS)),
    buildTagMap(TIFF_6_TAG_DEFINITIONS, ARRAY_SIZE(TIFF_6_TAG_DEFINITIONS))
};

TiffWriter::TiffWriter() : mTagMaps(sTagMaps), mNumTagMaps(DEFAULT_NUM_TAG_MAPS) {}

TiffWriter::TiffWriter(KeyedVector<uint16_t, const TagDefinition_t*>* enabledDefinitions,
        size_t length) : mTagMaps(enabledDefinitions), mNumTagMaps(length) {}

TiffWriter::~TiffWriter() {}

status_t TiffWriter::write(Output* out, StripSource** sources, size_t sourcesCount,
        Endianness end) {
    status_t ret = OK;
    EndianOutput endOut(out, end);

    if (mIfd == NULL) {
        ALOGE("%s: Tiff header is empty.", __FUNCTION__);
        return BAD_VALUE;
    }

    uint32_t totalSize = getTotalSize();

    KeyedVector<uint32_t, uint32_t> offsetVector;

    for (size_t i = 0; i < mNamedIfds.size(); ++i) {
        if (mNamedIfds[i]->uninitializedOffsets()) {
            uint32_t stripSize = mNamedIfds[i]->getStripSize();
            if (mNamedIfds[i]->setStripOffset(totalSize) != OK) {
                ALOGE("%s: Could not set strip offsets.", __FUNCTION__);
                return BAD_VALUE;
            }
            totalSize += stripSize;
            WORD_ALIGN(totalSize);
            offsetVector.add(mNamedIfds.keyAt(i), totalSize);
        }
    }

    size_t offVecSize = offsetVector.size();
    if (offVecSize != sourcesCount) {
        ALOGE("%s: Mismatch between number of IFDs with uninitialized strips (%zu) and"
                " sources (%zu).", __FUNCTION__, offVecSize, sourcesCount);
        return BAD_VALUE;
    }

    BAIL_ON_FAIL(writeFileHeader(endOut), ret);

    uint32_t offset = FILE_HEADER_SIZE;
    sp<TiffIfd> ifd = mIfd;
    while(ifd != NULL) {
        BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
        offset += ifd->getSize();
        ifd = ifd->getNextIfd();
    }

    if (LOG_NDEBUG == 0) {
        log();
    }

    for (size_t i = 0; i < offVecSize; ++i) {
        uint32_t ifdKey = offsetVector.keyAt(i);
        uint32_t sizeToWrite = mNamedIfds[ifdKey]->getStripSize();
        bool found = false;
        for (size_t j = 0; j < sourcesCount; ++j) {
            if (sources[j]->getIfd() == ifdKey) {
                if ((ret = sources[i]->writeToStream(endOut, sizeToWrite)) != OK) {
                    ALOGE("%s: Could not write to stream, received %d.", __FUNCTION__, ret);
                    return ret;
                }
                ZERO_TILL_WORD(&endOut, sizeToWrite, ret);
                found = true;
                break;
            }
        }
        if (!found) {
            ALOGE("%s: No stream for byte strips for IFD %u", __FUNCTION__, ifdKey);
            return BAD_VALUE;
        }
        assert(offsetVector[i] == endOut.getCurrentOffset());
    }

    return ret;
}

status_t TiffWriter::write(Output* out, Endianness end) {
    status_t ret = OK;
    EndianOutput endOut(out, end);

    if (mIfd == NULL) {
        ALOGE("%s: Tiff header is empty.", __FUNCTION__);
        return BAD_VALUE;
    }
    BAIL_ON_FAIL(writeFileHeader(endOut), ret);

    uint32_t offset = FILE_HEADER_SIZE;
    sp<TiffIfd> ifd = mIfd;
    while(ifd != NULL) {
        BAIL_ON_FAIL(ifd->writeData(offset, &endOut), ret);
        offset += ifd->getSize();
        ifd = ifd->getNextIfd();
    }
    return ret;
}


const TagDefinition_t* TiffWriter::lookupDefinition(uint16_t tag) const {
    const TagDefinition_t* definition = NULL;
    for (size_t i = 0; i < mNumTagMaps; ++i) {
        ssize_t index = mTagMaps[i].indexOfKey(tag);
        if (index >= 0) {
            definition = mTagMaps[i][index];
            break;
        }
    }

    if (definition == NULL) {
        ALOGE("%s: No definition exists for tag with id %x.", __FUNCTION__, tag);
    }
    return definition;
}

sp<TiffEntry> TiffWriter::getEntry(uint16_t tag, uint32_t ifd) const {
    ssize_t index = mNamedIfds.indexOfKey(ifd);
    if (index < 0) {
        ALOGE("%s: No IFD %d set for this writer.", __FUNCTION__, ifd);
        return NULL;
    }
    return mNamedIfds[index]->getEntry(tag);
}

void TiffWriter::removeEntry(uint16_t tag, uint32_t ifd) {
    ssize_t index = mNamedIfds.indexOfKey(ifd);
    if (index >= 0) {
        mNamedIfds[index]->removeEntry(tag);
    }
}

status_t TiffWriter::addEntry(const sp<TiffEntry>& entry, uint32_t ifd) {
    uint16_t tag = entry->getTag();

    const TagDefinition_t* definition = lookupDefinition(tag);

    if (definition == NULL) {
        ALOGE("%s: No definition exists for tag 0x%x.", __FUNCTION__, tag);
        return BAD_INDEX;
    }

    ssize_t index = mNamedIfds.indexOfKey(ifd);

    // Add a new IFD if necessary
    if (index < 0) {
        ALOGE("%s: No IFD %u exists.", __FUNCTION__, ifd);
        return NAME_NOT_FOUND;
    }

    sp<TiffIfd> selectedIfd  = mNamedIfds[index];
    return selectedIfd->addEntry(entry);
}

status_t TiffWriter::addStrip(uint32_t ifd) {
    ssize_t index = mNamedIfds.indexOfKey(ifd);
    if (index < 0) {
        ALOGE("%s: Ifd %u doesn't exist, cannot add strip entries.", __FUNCTION__, ifd);
        return BAD_VALUE;
    }
    sp<TiffIfd> selected = mNamedIfds[index];
    return selected->validateAndSetStripTags();
}

status_t TiffWriter::addIfd(uint32_t ifd) {
    ssize_t index = mNamedIfds.indexOfKey(ifd);
    if (index >= 0) {
        ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
        return BAD_VALUE;
    }

    sp<TiffIfd> newIfd = new TiffIfd(ifd);
    if (mIfd == NULL) {
        mIfd = newIfd;
    } else {
        sp<TiffIfd> last = findLastIfd();
        last->setNextIfd(newIfd);
    }

    if(mNamedIfds.add(ifd, newIfd) < 0) {
        ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
        return BAD_VALUE;
    }

    return OK;
}

status_t TiffWriter::addSubIfd(uint32_t parentIfd, uint32_t ifd, SubIfdType type) {
    ssize_t index = mNamedIfds.indexOfKey(ifd);
    if (index >= 0) {
        ALOGE("%s: Ifd with ID 0x%x already exists.", __FUNCTION__, ifd);
        return BAD_VALUE;
    }

    ssize_t parentIndex = mNamedIfds.indexOfKey(parentIfd);
    if (parentIndex < 0) {
        ALOGE("%s: Parent IFD with ID 0x%x does not exist.", __FUNCTION__, parentIfd);
        return BAD_VALUE;
    }

    sp<TiffIfd> parent = mNamedIfds[parentIndex];
    sp<TiffIfd> newIfd = new TiffIfd(ifd);

    uint16_t subIfdTag;
    if (type == SUBIFD) {
        subIfdTag = TAG_SUBIFDS;
    } else if (type == GPSINFO) {
        subIfdTag = TAG_GPSINFO;
    } else {
        ALOGE("%s: Unknown SubIFD type %d.", __FUNCTION__, type);
        return BAD_VALUE;
    }

    sp<TiffEntry> subIfds = parent->getEntry(subIfdTag);
    if (subIfds == NULL) {
        if (buildEntry(subIfdTag, 1, &newIfd, &subIfds) < 0) {
            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
            return BAD_VALUE;
        }
    } else {
        if (type == GPSINFO) {
            ALOGE("%s: Cannot add GPSInfo SubIFD to IFD %u, one already exists.", __FUNCTION__,
                    ifd);
            return BAD_VALUE;
        }

        Vector<sp<TiffIfd> > subIfdList;
        const sp<TiffIfd>* oldIfdArray = subIfds->getData<sp<TiffIfd> >();
        if (subIfdList.appendArray(oldIfdArray, subIfds->getCount()) < 0) {
            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
            return BAD_VALUE;
        }

        if (subIfdList.add(newIfd) < 0) {
            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
            return BAD_VALUE;
        }

        uint32_t count = subIfdList.size();
        if (buildEntry(subIfdTag, count, subIfdList.array(), &subIfds) < 0) {
            ALOGE("%s: Failed to build SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
            return BAD_VALUE;
        }
    }

    if (parent->addEntry(subIfds) < 0) {
        ALOGE("%s: Failed to add SubIfd entry in IFD 0x%x.", __FUNCTION__, parentIfd);
        return BAD_VALUE;
    }

    if(mNamedIfds.add(ifd, newIfd) < 0) {
        ALOGE("%s: Failed to add new IFD 0x%x.", __FUNCTION__, ifd);
        return BAD_VALUE;
    }

    return OK;
}

TagType TiffWriter::getDefaultType(uint16_t tag) const {
    const TagDefinition_t* definition = lookupDefinition(tag);
    if (definition == NULL) {
        ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
        return UNKNOWN_TAGTYPE;
    }
    return definition->defaultType;
}

uint32_t TiffWriter::getDefaultCount(uint16_t tag) const {
    const TagDefinition_t* definition = lookupDefinition(tag);
    if (definition == NULL) {
        ALOGE("%s: Could not find definition for tag %x", __FUNCTION__, tag);
        return 0;
    }
    return definition->fixedCount;
}

bool TiffWriter::hasIfd(uint32_t ifd) const {
    ssize_t index = mNamedIfds.indexOfKey(ifd);
    return index >= 0;
}

bool TiffWriter::checkIfDefined(uint16_t tag) const {
    return lookupDefinition(tag) != NULL;
}

const char* TiffWriter::getTagName(uint16_t tag) const {
    const TagDefinition_t* definition = lookupDefinition(tag);
    if (definition == NULL) {
        return NULL;
    }
    return definition->tagName;
}

sp<TiffIfd> TiffWriter::findLastIfd() {
    sp<TiffIfd> ifd = mIfd;
    while(ifd != NULL) {
        sp<TiffIfd> nextIfd = ifd->getNextIfd();
        if (nextIfd == NULL) {
            break;
        }
        ifd = nextIfd;
    }
    return ifd;
}

status_t TiffWriter::writeFileHeader(EndianOutput& out) {
    status_t ret = OK;
    uint16_t endMarker = (out.getEndianness() == BIG) ? BIG_ENDIAN_MARKER : LITTLE_ENDIAN_MARKER;
    BAIL_ON_FAIL(out.write(&endMarker, 0, 1), ret);

    uint16_t tiffMarker = TIFF_FILE_MARKER;
    BAIL_ON_FAIL(out.write(&tiffMarker, 0, 1), ret);

    uint32_t offsetMarker = FILE_HEADER_SIZE;
    BAIL_ON_FAIL(out.write(&offsetMarker, 0, 1), ret);
    return ret;
}

uint32_t TiffWriter::getTotalSize() const {
    uint32_t totalSize = FILE_HEADER_SIZE;
    sp<TiffIfd> ifd = mIfd;
    while(ifd != NULL) {
        totalSize += ifd->getSize();
        ifd = ifd->getNextIfd();
    }
    return totalSize;
}

void TiffWriter::log() const {
    ALOGI("%s: TiffWriter:", __FUNCTION__);
    size_t length = mNamedIfds.size();
    for (size_t i = 0; i < length; ++i) {
        mNamedIfds[i]->log();
    }
}

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