/*
 * Copyright 2023 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkTiffUtility_codec_DEFINED
#define SkTiffUtility_codec_DEFINED

#include "include/core/SkData.h"
#include "include/core/SkRefCnt.h"

#include <cstddef>
#include <cstdint>
#include <memory>

namespace SkTiff {

// Constants for endian signature.
inline constexpr size_t kEndianSize = 4;
inline constexpr uint8_t kEndianBig[kEndianSize] = {'M', 'M', 0, 42};
inline constexpr uint8_t kEndianLittle[kEndianSize] = {'I', 'I', 42, 0};

// Constants for types.
inline constexpr uint16_t kTypeUnsignedByte = 1;
inline constexpr uint16_t kTypeAsciiString = 2;
inline constexpr uint16_t kTypeUnsignedShort = 3;
inline constexpr uint16_t kTypeUnsignedLong = 4;
inline constexpr uint16_t kTypeUnsignedRational = 5;
inline constexpr uint16_t kTypeSignedByte = 6;
inline constexpr uint16_t kTypeUndefined = 7;
inline constexpr uint16_t kTypeSignedShort = 8;
inline constexpr uint16_t kTypeSignedLong = 9;
inline constexpr uint16_t kTypeSignedRational = 10;
inline constexpr uint16_t kTypeSingleFloat = 11;
inline constexpr uint16_t kTypeDoubleFloat = 12;

/*
 * Helper function for parsing a Tiff Image File Directory (IFD) structure. This structure is used
 * by EXIF tags, multi-picture, and maker note metadata.
 */
class ImageFileDirectory {
public:
    /*
     * Parse |data| to read the endian-ness into |outLittleEndian| and the IFD offset into
     * |outIfdOffset|. Return true if the endian-ness was successfully parsed and there was
     * the IFD offset was read.
     */
    static bool ParseHeader(const SkData* data, bool* outLittleEndian, uint32_t* outIfdOffset);

    /*
     * Create an object for parsing an IFD at offset |ifdOffset| inside |data| which has endianness
     * indicated by |littleEndian|. If |allowTruncated| is true, then parse as much of |data| as is
     * possible, otherwise reject any incomplete IFDs.
     */
    static std::unique_ptr<ImageFileDirectory> MakeFromOffset(sk_sp<SkData> data,
                                                              bool littleEndian,
                                                              uint32_t ifdOffset,
                                                              bool allowTruncated = false);

    /*
     * Return the number of entries.
     */
    uint16_t getNumEntries() const { return fNumEntries; }

    /*
     * Return the offset (within the specified SkData) of the next IFD in the list of IFDs.
     */
    uint32_t nextIfdOffset() const { return fNextIfdOffset; }

    /*
     * Return the tag, of a specific entry.
     */
    uint16_t getEntryTag(uint16_t entryIndex) const;

    /*
     * If |entryIndex| has type unsigned short (3), unsigned long (4), or signed rational (10), and
     * count |count|, then populate |values| with the data for the tag and return true. Otherwise
     * return false.
     */
    bool getEntryUnsignedShort(uint16_t entryIndex, uint32_t count, uint16_t* values) const {
        return getEntryValuesGeneric(entryIndex, kTypeUnsignedShort, count, values);
    }
    bool getEntryUnsignedLong(uint16_t entryIndex, uint32_t count, uint32_t* values) const {
        return getEntryValuesGeneric(entryIndex, kTypeUnsignedLong, count, values);
    }
    bool getEntrySignedRational(uint16_t entryIndex, uint32_t count, float* values) const {
        return getEntryValuesGeneric(entryIndex, kTypeSignedRational, count, values);
    }
    bool getEntryUnsignedRational(uint16_t entryIndex, uint32_t count, float* values) const {
        return getEntryValuesGeneric(entryIndex, kTypeUnsignedRational, count, values);
    }

    /*
     * If |entryIndex| has type undefined (7), then return the bytes specified by the count field
     * and the offset (read from the value field as an unsigned long).
     */
    sk_sp<SkData> getEntryUndefinedData(uint16_t entryIndex) const;

private:
    static bool IsValidType(uint16_t type);
    static size_t BytesForType(uint16_t type);

    ImageFileDirectory(sk_sp<SkData> data,
                       bool littleEndian,
                       uint32_t offset,
                       uint16_t ifdNumEntries,
                       uint32_t ifdNextOffset);

    /*
     * Return the tag, type, count, and data for the specified entry. Return false if the type
     * is invalid, or if the data in the IFD is out of bounds.
     */
    bool getEntryRawData(uint16_t entryIndex,
                         uint16_t* outTag,
                         uint16_t* outType,
                         uint32_t* outCount,
                         const uint8_t** outData,
                         size_t* outDataSize) const;

    /*
     * Helper function for assorted getTag functions.
     */
    bool getEntryValuesGeneric(uint16_t entryIndex,
                               uint16_t type,
                               uint32_t count,
                               void* values) const;

    // The data that the IFD indexes into.
    const sk_sp<SkData> fData;

    // True if the data is little endian.
    const bool fLittleEndian;

    // The offset where the IFD starts.
    const uint32_t fOffset;

    // The number of entries of the IFD (read from the first 2 bytes at the IFD offset).
    const uint16_t fNumEntries;

    // The offset of the next IFD (read from the next 4 bytes after the IFD entries).
    const uint32_t fNextIfdOffset;
};

}  // namespace SkTiff

#endif
