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

#include "include/private/SkExif.h"

#include "include/core/SkData.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkStream.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkTiffUtility.h"
#include "src/core/SkStreamPriv.h"

#if defined(SK_EXIF_PARSE_WITH_RUST)
#include "rust/exif/FFI.h"
#include "rust/exif/FFI.rs.h"
#endif

#include <algorithm>
#include <cmath>
#include <cstring>
#include <memory>
#include <utility>

namespace SkExif {

constexpr uint16_t kSubIFDOffsetTag = 0x8769;

#if !defined(SK_EXIF_PARSE_WITH_RUST)
constexpr uint16_t kMarkerNoteTag = 0x927c;

static std::optional<float> get_maker_note_hdr_headroom(sk_sp<SkData> data) {
    // No little endian images that specify this data have been observed. Do not add speculative
    // support.
    const bool kLittleEndian = false;
    const uint8_t kSig[] = {
            'A', 'p', 'p', 'l', 'e', ' ', 'i', 'O', 'S', 0, 0, 1, 'M', 'M',  //
    };
    if (!data || data->size() < sizeof(kSig)) {
        return std::nullopt;
    }
    if (memcmp(data->data(), kSig, sizeof(kSig)) != 0) {
        return std::nullopt;
    }
    auto ifd = SkTiff::ImageFileDirectory::MakeFromOffset(
            std::move(data), kLittleEndian, sizeof(kSig));
    if (!ifd) {
        return std::nullopt;
    }

    // See documentation at:
    // https://developer.apple.com/documentation/appkit/images_and_pdf/applying_apple_hdr_effect_to_your_photos
    bool hasMaker33 = false;
    bool hasMaker48 = false;
    float maker33 = 0.f;
    float maker48 = 0.f;
    for (uint32_t i = 0; i < ifd->getNumEntries(); ++i) {
        switch (ifd->getEntryTag(i)) {
            case 33:
                if (!hasMaker33) {
                    hasMaker33 = ifd->getEntrySignedRational(i, 1, &maker33);
                }
                break;
            case 48:
                if (!hasMaker48) {
                    hasMaker48 = ifd->getEntrySignedRational(i, 1, &maker48);
                }
                break;
            default:
                break;
        }
    }
    // Many images have a maker33 but not a maker48. Treat them as having maker48 of 0.
    if (!hasMaker33) {
        return std::nullopt;
    }
    float stops = 0.f;
    if (maker33 < 1.0f) {
        if (maker48 <= 0.01f) {
            stops = -20.0f * maker48 + 1.8f;
        } else {
            stops = -0.101f * maker48 + 1.601f;
        }
    } else {
        if (maker48 <= 0.01f) {
            stops = -70.0f * maker48 + 3.0f;
        } else {
            stops = -0.303f * maker48 + 2.303f;
        }
    }
    return std::pow(2.f, std::max(stops, 0.f));
}

static void parse_ifd(Metadata& exif,
                      sk_sp<SkData> data,
                      std::unique_ptr<SkTiff::ImageFileDirectory> ifd,
                      bool littleEndian,
                      bool isRoot) {
    if (!ifd) {
        return;
    }
    for (uint32_t i = 0; i < ifd->getNumEntries(); ++i) {
        switch (ifd->getEntryTag(i)) {
            case kOriginTag: {
                uint16_t value = 0;
                if (!exif.fOrigin.has_value() && ifd->getEntryUnsignedShort(i, 1, &value)) {
                    if (0 < value && value <= kLast_SkEncodedOrigin) {
                        exif.fOrigin = static_cast<SkEncodedOrigin>(value);
                    }
                }
                break;
            }
            case kMarkerNoteTag:
                if (!exif.fHdrHeadroom.has_value()) {
                    if (auto makerNoteData = ifd->getEntryUndefinedData(i)) {
                        exif.fHdrHeadroom = get_maker_note_hdr_headroom(std::move(makerNoteData));
                    }
                }
                break;
            case kSubIFDOffsetTag: {
                uint32_t subIfdOffset = 0;
                if (isRoot && ifd->getEntryUnsignedLong(i, 1, &subIfdOffset)) {
                    auto subIfd = SkTiff::ImageFileDirectory::MakeFromOffset(
                            data, littleEndian, subIfdOffset, /*allowTruncated=*/true);
                    parse_ifd(exif,
                              data,
                              std::move(subIfd),
                              littleEndian,
                              /*isRoot=*/false);
                }
                break;
            }
            case kXResolutionTag: {
                float value = 0.f;
                if (!exif.fXResolution.has_value() && ifd->getEntryUnsignedRational(i, 1, &value)) {
                    exif.fXResolution = value;
                }
                break;
            }
            case kYResolutionTag: {
                float value = 0.f;
                if (!exif.fYResolution.has_value() && ifd->getEntryUnsignedRational(i, 1, &value)) {
                    exif.fYResolution = value;
                }
                break;
            }
            case kResolutionUnitTag: {
                uint16_t value = 0;
                if (!exif.fResolutionUnit.has_value() && ifd->getEntryUnsignedShort(i, 1, &value)) {
                    exif.fResolutionUnit = value;
                }
                break;
            }
            case kPixelXDimensionTag: {
                // The type for this tag can be unsigned short or unsigned long (as per the Exif 2.3
                // spec, aka CIPA DC-008-2012). Support for unsigned long was added in
                // https://crrev.com/817600.
                uint16_t value16 = 0;
                if (!exif.fPixelXDimension.has_value() &&
                    ifd->getEntryUnsignedShort(i, 1, &value16)) {
                    exif.fPixelXDimension = value16;
                }
                uint32_t value32 = 0;
                if (!exif.fPixelXDimension.has_value() &&
                    ifd->getEntryUnsignedLong(i, 1, &value32)) {
                    exif.fPixelXDimension = value32;
                }
                break;
            }
            case kPixelYDimensionTag: {
                uint16_t value16 = 0;
                if (!exif.fPixelYDimension.has_value() &&
                    ifd->getEntryUnsignedShort(i, 1, &value16)) {
                    exif.fPixelYDimension = value16;
                }
                uint32_t value32 = 0;
                if (!exif.fPixelYDimension.has_value() &&
                    ifd->getEntryUnsignedLong(i, 1, &value32)) {
                    exif.fPixelYDimension = value32;
                }
                break;
            }
            default:
                break;
        }
    }
}
#endif

void Parse(Metadata& metadata, const SkData* data) {
#if defined(SK_EXIF_PARSE_WITH_RUST)
    if (data) {
        rust_exif::ExifMetadata rustMeta;
        if (rust_exif::parse_exif(
                    rust::Slice<const uint8_t>(data->bytes(), data->size()), rustMeta)) {
            rust_exif::ToSkExifMetadata(rustMeta, &metadata);
        }
    }
#else
    bool littleEndian = false;
    uint32_t ifdOffset = 0;
    if (data && SkTiff::ImageFileDirectory::ParseHeader(data, &littleEndian, &ifdOffset)) {
        auto dataRef = SkData::MakeWithoutCopy(data->data(), data->size());
        auto ifd = SkTiff::ImageFileDirectory::MakeFromOffset(
                dataRef, littleEndian, ifdOffset, /*allowTruncated=*/true);
        parse_ifd(metadata, std::move(dataRef), std::move(ifd), littleEndian, /*isRoot=*/true);
    }
#endif
}

// Helper function to write a single IFD entry.
bool write_entry(uint16_t tag, uint16_t type, uint32_t count, uint32_t value,
                uint32_t* endOfData, SkWStream* stream, SkWStream* buffer) {
    bool success = true;
    success &= SkStreamPriv::WriteU16BE(stream, tag);
    success &= SkStreamPriv::WriteU16BE(stream, type);
    success &= SkStreamPriv::WriteU32BE(stream, count);
    switch (tag) {
      case kOriginTag:
      case kResolutionUnitTag:
          success &= SkStreamPriv::WriteU16BE(stream, value);
          success &= SkStreamPriv::WriteU16BE(stream, 0);  // Complete the IFD entry.
          return success;
      case kPixelXDimensionTag:
      case kPixelYDimensionTag:
          success &= SkStreamPriv::WriteU32BE(stream, value);
          return success;
      case kXResolutionTag:
      case kYResolutionTag:
        // If the number of bytes for the type of the entry is greater than 4, we have
        // to append the value to the end and replace the value section with an offset
        // to where the data can be found.
        success &= SkStreamPriv::WriteU32BE(stream, *endOfData);
        *endOfData += 8;
        success &= SkStreamPriv::WriteU32BE(buffer, value);  // Numerator
        success &= SkStreamPriv::WriteU32BE(buffer, 1);      // Denominator
        return success;
      case kSubIFDOffsetTag:
        // This does not write the subIFD itself, just the IFD0 entry that points
        // to where it is located.
        success &= SkStreamPriv::WriteU32BE(stream, value);
        return success;
      default:
        return false;
    }
}

sk_sp<SkData> WriteExif(Metadata& metadata) {
    // Cannot write an IFD entry for MakerNote from the HDR Headroom. Information
    // about maker48 and maker33 is lost in encode.
    // See documentation at:
    // https://developer.apple.com/documentation/appkit/images_and_pdf/applying_apple_hdr_effect_to_your_photos
    if (metadata.fHdrHeadroom.has_value()) {
        SkCodecPrintf("Cannot encode maker noter from the headroom value.\n");
        return nullptr;
    }

    SkDynamicMemoryWStream stream;
    // If there exists metadata that belongs in a subIFD, we will write that to a
    // separate stream and append it to the end of the data, before |bufferForLargerValues|.
    bool subIFDExists = false;
    // This buffer will hold the values that are more than 4 bytes and will be
    // appended to the end of the data after going through all available fields.
    SkDynamicMemoryWStream bufferForLargerValues;
    constexpr uint32_t kOffset = 8;

    // Write the IFD header.
    if (!stream.write(SkTiff::kEndianBig, sizeof(SkTiff::kEndianBig))) {
      return nullptr;
    }
    // Offset of index IFD.
    if (!SkStreamPriv::WriteU32BE(&stream, kOffset)) {
        return nullptr;
    }
    // Count the number of valid metadata entries.
    uint16_t numTags = 0;
    uint16_t numSubIFDTags = 0;
    if (metadata.fOrigin.has_value()) numTags++;
    if (metadata.fResolutionUnit.has_value()) numTags++;
    if (metadata.fXResolution.has_value()) numTags++;
    if (metadata.fYResolution.has_value()) numTags++;
    if (metadata.fPixelXDimension.has_value()) numSubIFDTags++;
    if (metadata.fPixelYDimension.has_value()) numSubIFDTags++;
    if (numSubIFDTags > 0) {
      subIFDExists = true;
      numTags++;
    }

    // Offset that represents where data will be appended.
    uint32_t endOfData = kOffset
                        + SkTiff::kSizeShort  // Number of tags
                        + (SkTiff::kSizeEntry * numTags) // Entries
                        + SkTiff::kSizeLong; // Next IFD offset
    // Offset that represents where the subIFD will start if it exists.
    const uint32_t kSubIfdOffset = endOfData;
    if (subIFDExists) {
      endOfData += SkTiff::kSizeShort  // Number of subIFD tags
                  + (SkTiff::kSizeEntry * numSubIFDTags) // SubIFD entries
                  + SkTiff::kSizeLong; // SubIFD next offset;
    }

    // Write the number of tags in the IFD.
    SkStreamPriv::WriteU16BE(&stream, numTags);

    // Write the IFD entries.
    if (metadata.fOrigin.has_value()
        && !write_entry(kOriginTag, SkTiff::kTypeUnsignedShort, 1,
                        metadata.fOrigin.value(), &endOfData, &stream,
                        &bufferForLargerValues)) {
          return nullptr;
        }

    if (metadata.fResolutionUnit.has_value()
        && !write_entry(kResolutionUnitTag, SkTiff::kTypeUnsignedShort, 1,
                        metadata.fResolutionUnit.value(), &endOfData, &stream,
                        &bufferForLargerValues)) {
          return nullptr;
        }

    if (metadata.fXResolution.has_value()
        && !write_entry(kXResolutionTag, SkTiff::kTypeUnsignedRational, 1,
                        metadata.fXResolution.value(), &endOfData, &stream,
                        &bufferForLargerValues)) {
          return nullptr;
        }

    if (metadata.fYResolution.has_value()
        && !write_entry(kYResolutionTag, SkTiff::kTypeUnsignedRational, 1,
                        metadata.fYResolution.value(), &endOfData, &stream,
                        &bufferForLargerValues)) {
          return nullptr;
        }

    if (subIFDExists && !write_entry(kSubIFDOffsetTag, SkTiff::kTypeUnsignedLong, 1,
                      kSubIfdOffset, &endOfData, &stream, &bufferForLargerValues)) {
          return nullptr;
        }

    // Next IFD offset (0 for no next IFD).
        if (!SkStreamPriv::WriteU32BE(&stream, 0)) {
            return nullptr;
        }

    // After all IFD0 data has been written, then write the SubIFD (ExifIFD).
    if (subIFDExists) {
      // Write the number of tags in the subIFD.
      if (!SkStreamPriv::WriteU16BE(&stream, numSubIFDTags)) {
          return nullptr;
      }

      if (metadata.fPixelXDimension.has_value()
          && !write_entry(kPixelXDimensionTag, SkTiff::kTypeUnsignedLong, 1,
                          metadata.fPixelXDimension.value(), &endOfData, &stream,
                          &bufferForLargerValues)) {
            return nullptr;
          }

      if (metadata.fPixelYDimension.has_value()
          && !write_entry(kPixelYDimensionTag, SkTiff::kTypeUnsignedLong, 1,
                          metadata.fPixelYDimension.value(), &endOfData, &stream,
                          &bufferForLargerValues)) {
            return nullptr;
          }

          // Write the SubIFD next offset (0).
          if (!SkStreamPriv::WriteU32BE(&stream, 0)) {
              return nullptr;
          }
    }

    // Append the data buffer to the end of the stream.
    if (!bufferForLargerValues.writeToStream(&stream)) {
        return nullptr;
    }

    return stream.detachAsData();
}

}  // namespace SkExif
