// Copyright 2015 Google Inc.
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////

#include "src/piex.h"

#include <cstdint>
#include <limits>
#include <set>
#include <vector>

#include "src/binary_parse/range_checked_byte_ptr.h"
#include "src/image_type_recognition/image_type_recognition_lite.h"
#include "src/piex_cr3.h"
#include "src/tiff_parser.h"

namespace piex {
namespace {

using binary_parse::RangeCheckedBytePtr;
using image_type_recognition::RawImageTypes;
using image_type_recognition::RecognizeRawImageTypeLite;
using tiff_directory::Endian;
using tiff_directory::TiffDirectory;

const std::uint32_t kRafOffsetToPreviewOffset = 84;

bool GetDngInformation(const tiff_directory::TiffDirectory& tiff_directory,
                       std::uint32_t* width, std::uint32_t* height,
                       std::vector<std::uint32_t>* cfa_pattern_dim) {
  if (!GetFullDimension32(tiff_directory, width, height) || *width == 0 ||
      *height == 0) {
    return false;
  }

  if (!tiff_directory.Get(kTiffTagCfaPatternDim, cfa_pattern_dim) ||
      cfa_pattern_dim->size() != 2) {
    return false;
  }
  return true;
}

bool GetDngInformation(const TagSet& extended_tags, StreamInterface* data,
                       std::uint32_t* width, std::uint32_t* height,
                       std::vector<std::uint32_t>* cfa_pattern_dim) {
  TagSet desired_tags = {kExifTagDefaultCropSize, kTiffTagCfaPatternDim,
                         kTiffTagExifIfd, kTiffTagSubFileType};
  desired_tags.insert(extended_tags.cbegin(), extended_tags.cend());

  TiffParser tiff_parser(data, 0 /* offset */);

  TiffContent tiff_content;
  if (!tiff_parser.Parse(desired_tags, 1, &tiff_content) ||
      tiff_content.tiff_directory.empty()) {
    return false;
  }

  // If IFD0 contains already the full dimensions we do not parse into the sub
  // IFD.
  const TiffDirectory& tiff_directory = tiff_content.tiff_directory[0];
  if (tiff_directory.GetSubDirectories().empty()) {
    return GetDngInformation(tiff_directory, width, height, cfa_pattern_dim);
  } else {
    return GetDngInformation(tiff_directory.GetSubDirectories()[0], width,
                             height, cfa_pattern_dim);
  }
}

bool GetPreviewData(const TagSet& extended_tags,
                    const std::uint32_t tiff_offset,
                    const std::uint32_t number_of_ifds, StreamInterface* stream,
                    TiffContent* tiff_content,
                    PreviewImageData* preview_image_data) {
  TagSet desired_tags = {
      kExifTagColorSpace, kExifTagDateTimeOriginal, kExifTagExposureTime,
      kExifTagFnumber,    kExifTagFocalLength,      kExifTagGps,
      kExifTagIsoSpeed,   kTiffTagCompression,      kTiffTagDateTime,
      kTiffTagExifIfd,    kTiffTagCfaPatternDim,    kTiffTagMake,
      kTiffTagModel,      kTiffTagOrientation,      kTiffTagPhotometric};
  desired_tags.insert(extended_tags.cbegin(), extended_tags.cend());

  TiffParser tiff_parser(stream, tiff_offset);

  if (!tiff_parser.Parse(desired_tags, number_of_ifds, tiff_content)) {
    return false;
  }
  if (tiff_content->tiff_directory.empty()) {
    // Returns false if the stream does not contain any TIFF structure.
    return false;
  }
  return tiff_parser.GetPreviewImageData(*tiff_content, preview_image_data);
}

bool GetPreviewData(const TagSet& extended_tags,
                    const std::uint32_t number_of_ifds, StreamInterface* stream,
                    PreviewImageData* preview_image_data) {
  const std::uint32_t kTiffOffset = 0;
  TiffContent tiff_content;
  return GetPreviewData(extended_tags, kTiffOffset, number_of_ifds, stream,
                        &tiff_content, preview_image_data);
}

bool GetExifData(const std::uint32_t exif_offset, StreamInterface* stream,
                 PreviewImageData* preview_image_data) {
  const TagSet kExtendedTags = {kTiffTagJpegByteCount, kTiffTagJpegOffset};
  const std::uint32_t kNumberOfIfds = 2;
  TiffContent tiff_content;
  return GetPreviewData(kExtendedTags, exif_offset, kNumberOfIfds, stream,
                        &tiff_content, preview_image_data);
}

// Reads the jpeg compressed thumbnail information.
void GetThumbnailOffsetAndLength(const TagSet& extended_tags,
                                 StreamInterface* stream,
                                 PreviewImageData* preview_image_data) {
  TagSet desired_tags = {kTiffTagJpegByteCount, kTiffTagJpegOffset};
  desired_tags.insert(extended_tags.cbegin(), extended_tags.cend());

  const std::uint32_t kNumberOfIfds = 2;
  PreviewImageData thumbnail_data;
  if (GetPreviewData(desired_tags, kNumberOfIfds, stream, &thumbnail_data)) {
    preview_image_data->thumbnail = thumbnail_data.thumbnail;
  }
}

bool GetExifIfd(const Endian endian, StreamInterface* stream,
                TiffDirectory* exif_ifd) {
  const std::uint32_t kTiffOffset = 0;
  std::uint32_t offset_to_ifd;
  if (!Get32u(stream, sizeof(offset_to_ifd), endian, &offset_to_ifd)) {
    return false;
  }

  std::uint32_t next_ifd_offset;
  TiffDirectory tiff_ifd(endian);
  if (!ParseDirectory(kTiffOffset, offset_to_ifd, endian, {kTiffTagExifIfd},
                      stream, &tiff_ifd, &next_ifd_offset)) {
    return false;
  }

  std::uint32_t exif_offset;
  if (tiff_ifd.Get(kTiffTagExifIfd, &exif_offset)) {
    return ParseDirectory(kTiffOffset, exif_offset, endian,
                          {kExifTagMakernotes}, stream, exif_ifd,
                          &next_ifd_offset);
  }

  return true;
}

bool GetMakernoteIfd(const TiffDirectory& exif_ifd, const Endian endian,
                     const std::uint32_t skip_offset, StreamInterface* stream,
                     std::uint32_t* makernote_offset,
                     TiffDirectory* makernote_ifd) {
  std::uint32_t makernote_length;
  if (!exif_ifd.GetOffsetAndLength(kExifTagMakernotes,
                                   tiff_directory::TIFF_TYPE_UNDEFINED,
                                   makernote_offset, &makernote_length)) {
    return false;
  }

  std::uint32_t next_ifd_offset;
  return ParseDirectory(*makernote_offset, *makernote_offset + skip_offset,
                        endian, {kTiffTagImageWidth, kOlymTagCameraSettings,
                                 kOlymTagRawProcessing, kPentaxTagColorSpace},
                        stream, makernote_ifd, &next_ifd_offset);
}

bool GetCameraSettingsIfd(const TiffDirectory& makernote_ifd,
                          const std::uint32_t makernote_offset,
                          const Endian endian, StreamInterface* stream,
                          TiffDirectory* camera_settings_ifd) {
  std::uint32_t camera_settings_offset;
  std::uint32_t camera_settings_length;
  if (!makernote_ifd.GetOffsetAndLength(
          kOlymTagCameraSettings, tiff_directory::TIFF_IFD,
          &camera_settings_offset, &camera_settings_length)) {
    return false;
  }

  std::uint32_t next_ifd_offset;
  if (!Get32u(stream, camera_settings_offset, endian,
              &camera_settings_offset)) {
    return false;
  }
  return ParseDirectory(makernote_offset,
                        makernote_offset + camera_settings_offset, endian,
                        {kTiffTagBitsPerSample, kTiffTagImageLength}, stream,
                        camera_settings_ifd, &next_ifd_offset);
}

bool GetRawProcessingIfd(const TagSet& desired_tags,
                         const TiffDirectory& makernote_ifd,
                         const std::uint32_t makernote_offset,
                         const Endian endian, StreamInterface* stream,
                         TiffDirectory* raw_processing_ifd) {
  std::uint32_t raw_processing_offset;
  std::uint32_t raw_processing_length;
  if (!makernote_ifd.GetOffsetAndLength(
          kOlymTagRawProcessing, tiff_directory::TIFF_IFD,
          &raw_processing_offset, &raw_processing_length)) {
    return false;
  }

  std::uint32_t next_ifd_offset;
  if (!Get32u(stream, raw_processing_offset, endian, &raw_processing_offset)) {
    return false;
  }

  return ParseDirectory(
      makernote_offset, makernote_offset + raw_processing_offset, endian,
      desired_tags, stream, raw_processing_ifd, &next_ifd_offset);
}

// Retrieves the preview image offset and length from the camera settings and
// the 'full_width' and 'full_height' from the raw processing ifd in 'stream'.
// Returns false if anything is wrong.
bool GetOlympusPreviewImage(StreamInterface* stream,
                            PreviewImageData* preview_image_data) {
  Endian endian;
  if (!GetEndianness(0 /* tiff offset */, stream, &endian)) {
    return false;
  }

  TiffDirectory exif_ifd(endian);
  if (!GetExifIfd(endian, stream, &exif_ifd)) {
    return false;
  }

  std::uint32_t makernote_offset;
  TiffDirectory makernote_ifd(endian);
  const std::uint32_t kSkipMakernoteStart = 12;
  if (!GetMakernoteIfd(exif_ifd, endian, kSkipMakernoteStart, stream,
                       &makernote_offset, &makernote_ifd)) {
    return false;
  }

  const std::uint32_t kThumbnailTag = 0x0100;
  if (makernote_ifd.Has(kThumbnailTag)) {
    if (!makernote_ifd.GetOffsetAndLength(
            kThumbnailTag, tiff_directory::TIFF_TYPE_UNDEFINED,
            &preview_image_data->thumbnail.offset,
            &preview_image_data->thumbnail.length)) {
      return false;
    }
  }

  TiffDirectory camera_settings_ifd(endian);
  if (!GetCameraSettingsIfd(makernote_ifd, makernote_offset, endian, stream,
                            &camera_settings_ifd)) {
    return false;
  }

  const std::uint32_t kPreviewOffset = 0x0101;
  const std::uint32_t kPreviewLength = 0x0102;
  if (!camera_settings_ifd.Has(kPreviewOffset) ||
      !camera_settings_ifd.Has(kPreviewLength)) {
    return false;
  }

  camera_settings_ifd.Get(kPreviewOffset, &preview_image_data->preview.offset);
  preview_image_data->preview.offset += makernote_offset;
  camera_settings_ifd.Get(kPreviewLength, &preview_image_data->preview.length);

  // Get the crop size from the raw processing ifd.
  TiffDirectory raw_processing_ifd(endian);
  if (!GetRawProcessingIfd({kOlymTagAspectFrame}, makernote_ifd,
                           makernote_offset, endian, stream,
                           &raw_processing_ifd)) {
    return false;
  }

  if (raw_processing_ifd.Has(kOlymTagAspectFrame)) {
    std::vector<std::uint32_t> aspect_frame(4);
    if (raw_processing_ifd.Get(kOlymTagAspectFrame, &aspect_frame) &&
        aspect_frame[2] > aspect_frame[0] &&
        aspect_frame[3] > aspect_frame[1]) {
      preview_image_data->full_width = aspect_frame[2] - aspect_frame[0] + 1;
      preview_image_data->full_height = aspect_frame[3] - aspect_frame[1] + 1;
      if (preview_image_data->full_width < preview_image_data->full_height) {
        std::swap(preview_image_data->full_width,
                  preview_image_data->full_height);
      }
    }
  }

  return true;
}

bool PefGetColorSpace(StreamInterface* stream,
                      PreviewImageData* preview_image_data) {
  Endian endian;
  if (!GetEndianness(0 /* tiff offset */, stream, &endian)) {
    return false;
  }

  TiffDirectory exif_ifd(endian);
  if (!GetExifIfd(endian, stream, &exif_ifd)) {
    return false;
  }

  std::uint32_t makernote_offset;
  TiffDirectory makernote_ifd(endian);
  const std::uint32_t kSkipMakernoteStart = 6;
  if (!GetMakernoteIfd(exif_ifd, endian, kSkipMakernoteStart, stream,
                       &makernote_offset, &makernote_ifd)) {
    return false;
  }
  if (makernote_ifd.Has(kPentaxTagColorSpace)) {
    std::uint32_t color_space;
    if (!makernote_ifd.Get(kPentaxTagColorSpace, &color_space)) {
      return false;
    }
    preview_image_data->color_space = color_space == 0
                                          ? PreviewImageData::kSrgb
                                          : PreviewImageData::kAdobeRgb;
  }
  return true;
}

bool RafGetOrientation(StreamInterface* stream, std::uint32_t* orientation) {
  // Parse the Fuji RAW header to get the offset and length of the preview
  // image, which contains the Exif information.
  const Endian endian = tiff_directory::kBigEndian;
  std::uint32_t preview_offset = 0;
  if (!Get32u(stream, kRafOffsetToPreviewOffset, endian, &preview_offset)) {
    return false;
  }

  const std::uint32_t exif_offset = preview_offset + 12;
  return GetExifOrientation(stream, exif_offset, orientation);
}

// Parses the Fuji Cfa header for the image width and height.
bool RafGetDimension(StreamInterface* stream, std::uint32_t* width,
                     std::uint32_t* height) {
  const Endian endian = tiff_directory::kBigEndian;
  std::uint32_t cfa_header_index = 0;  // actual position in the cfa header.
  std::uint32_t cfa_header_entries = 0;
  if (!Get32u(stream, 92 /* cfa header offset */, endian, &cfa_header_index) ||
      !Get32u(stream, cfa_header_index, endian, &cfa_header_entries)) {
    return false;
  }

  // Add 4 to point to the actual read position in the cfa header.
  cfa_header_index += 4;

  for (std::uint32_t i = 0; i < cfa_header_entries; ++i) {
    std::uint16_t id = 0;
    std::uint16_t length = 0;
    if (!Get16u(stream, cfa_header_index, endian, &id) ||
        !Get16u(stream, cfa_header_index + 2, endian, &length)) {
      return false;
    }

    std::uint16_t tmp_width = 0;
    std::uint16_t tmp_height = 0;
    if (id == 0x0111 /* tags the crop dimensions */ &&
        Get16u(stream, cfa_header_index + 4, endian, &tmp_height) &&
        Get16u(stream, cfa_header_index + 6, endian, &tmp_width)) {
      *width = tmp_width;
      *height = tmp_height;
      return true;
    }
    cfa_header_index += 4u + length;
  }
  return false;
}

Error ArwGetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  const TagSet extended_tags = {kExifTagHeight, kExifTagWidth,
                                kTiffTagJpegByteCount, kTiffTagJpegOffset,
                                kTiffTagSubIfd};

  GetThumbnailOffsetAndLength(TagSet(), stream, preview_image_data);

  const std::uint32_t kNumberOfIfds = 1;
  if (GetPreviewData(extended_tags, kNumberOfIfds, stream,
                     preview_image_data)) {
    return kOk;
  }
  return kFail;
}

Error Cr2GetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  const TagSet extended_tags = {kExifTagHeight, kExifTagWidth,
                                kTiffTagStripByteCounts, kTiffTagStripOffsets};

  GetThumbnailOffsetAndLength(TagSet(), stream, preview_image_data);

  const std::uint32_t kNumberOfIfds = 1;
  if (GetPreviewData(extended_tags, kNumberOfIfds, stream,
                     preview_image_data)) {
    return kOk;
  }
  return kFail;
}

Error DngGetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  // Some thumbnails from DngCreator are larger than the specified 256 pixel.
  const int kDngThumbnailMaxDimension = 512;

  const TagSet extended_tags = {
      kExifTagDefaultCropSize, kTiffTagImageWidth,   kTiffTagImageLength,
      kTiffTagStripByteCounts, kTiffTagStripOffsets, kTiffTagSubIfd};

  TiffContent tiff_content;
  const std::uint32_t kNumberOfIfds = 3;
  if (!GetPreviewData(extended_tags, 0, kNumberOfIfds, stream, &tiff_content,
                      preview_image_data)) {
    return kFail;
  }

  const TiffDirectory& tiff_directory = tiff_content.tiff_directory[0];

  if (!GetFullCropDimension(tiff_directory, &preview_image_data->full_width,
                            &preview_image_data->full_height)) {
    return kFail;
  }

  // Find the jpeg compressed thumbnail and preview image.
  Image preview;
  Image thumbnail;

  // Search for images in IFD0
  Image temp_image;
  if (GetImageData(tiff_directory, stream, &temp_image)) {
    if (IsThumbnail(temp_image, kDngThumbnailMaxDimension)) {
      thumbnail = temp_image;
    } else if (temp_image.format == Image::kJpegCompressed) {
      preview = temp_image;
    }
  }

  // Search for images in other IFDs
  for (const auto& ifd : tiff_directory.GetSubDirectories()) {
    if (GetImageData(ifd, stream, &temp_image)) {
      // Try to find the largest thumbnail/preview.
      if (IsThumbnail(temp_image, kDngThumbnailMaxDimension)) {
        if (temp_image > thumbnail) {
          thumbnail = temp_image;
        }
      } else {
        if (temp_image > preview &&
            temp_image.format == Image::kJpegCompressed) {
          preview = temp_image;
        }
      }
    }
  }
  preview_image_data->preview = preview;
  preview_image_data->thumbnail = thumbnail;

  return kOk;
}

Error NefGetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  const TagSet extended_tags = {kTiffTagImageWidth,      kTiffTagImageLength,
                                kTiffTagJpegByteCount,   kTiffTagJpegOffset,
                                kTiffTagStripByteCounts, kTiffTagStripOffsets,
                                kTiffTagSubIfd};
  const std::uint32_t kNumberOfIfds = 2;
  if (!GetPreviewData(extended_tags, kNumberOfIfds, stream,
                      preview_image_data)) {
    return kFail;
  }

  if (preview_image_data->thumbnail.length == 0) {
    PreviewImageData thumbnail_data;
    GetThumbnailOffsetAndLength(TagSet(), stream, &thumbnail_data);
    preview_image_data->thumbnail = thumbnail_data.thumbnail;
  }

  // The Nikon RAW data provides the dimensions of the sensor image, which are
  // slightly larger than the dimensions of the preview image. In order to
  // determine the correct full width and height of the image, the preview image
  // size needs to be taken into account. Based on experiments the preview image
  // dimensions must be at least 90% of the sensor image dimensions to let it be
  // a full size preview image.
  if (preview_image_data->preview.length > 0) {  // when preview image exists
    const float kEpsilon = 0.9f;

    std::uint16_t width;
    std::uint16_t height;
    if (!GetJpegDimensions(preview_image_data->preview.offset, stream, &width,
                           &height) ||
        preview_image_data->full_width == 0 ||
        preview_image_data->full_height == 0) {
      return kUnsupported;
    }

    if (static_cast<float>(width) /
                static_cast<float>(preview_image_data->full_width) >
            kEpsilon ||
        static_cast<float>(height) /
                static_cast<float>(preview_image_data->full_height) >
            kEpsilon) {
      preview_image_data->full_width = width;
      preview_image_data->full_height = height;
    }
  }
  return kOk;
}

Error OrfGetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  if (!GetExifData(0, stream, preview_image_data)) {
    return kFail;
  }
  // Omit errors, because some images do not contain any preview data.
  GetOlympusPreviewImage(stream, preview_image_data);
  return kOk;
}

Error PefGetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  const TagSet extended_tags = {kTiffTagImageWidth, kTiffTagImageLength,
                                kTiffTagJpegByteCount, kTiffTagJpegOffset,
                                kTiffTagSubIfd};
  const std::uint32_t kNumberOfIfds = 3;
  if (!GetPreviewData(extended_tags, kNumberOfIfds, stream,
                      preview_image_data) ||
      !PefGetColorSpace(stream, preview_image_data)) {
    return kFail;
  }

  PreviewImageData thumbnail_data;
  GetThumbnailOffsetAndLength(TagSet(), stream, &thumbnail_data);
  preview_image_data->thumbnail = thumbnail_data.thumbnail;

  return kOk;
}

Error RafGetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  // Parse the Fuji RAW header to get the offset and length of the preview
  // image, which contains the Exif information.
  const Endian endian = tiff_directory::kBigEndian;
  std::uint32_t preview_offset = 0;
  std::uint32_t preview_length = 0;
  if (!Get32u(stream, kRafOffsetToPreviewOffset, endian, &preview_offset) ||
      !Get32u(stream, kRafOffsetToPreviewOffset + 4, endian, &preview_length)) {
    return kFail;
  }

  if (!RafGetDimension(stream, &preview_image_data->full_width,
                       &preview_image_data->full_height)) {
    return kFail;
  }

  if (preview_length > 0) {  // when preview image exists
    // Parse the Exif information from the preview image.
    const std::uint32_t exif_offset = preview_offset + 12;
    if (!GetExifData(exif_offset, stream, preview_image_data)) {
      return kFail;
    }
  }

  // Merge the Exif data with the RAW data to form the preview_image_data.
  preview_image_data->thumbnail.offset += 160;  // Skip the cfa header.
  preview_image_data->preview.offset = preview_offset;
  preview_image_data->preview.length = preview_length;
  return kOk;
}

Error Rw2GetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  const TagSet extended_tags = {kPanaTagTopBorder,     kPanaTagLeftBorder,
                                kPanaTagBottomBorder,  kPanaTagRightBorder,
                                kPanaTagIso,           kPanaTagJpegImage,
                                kTiffTagJpegByteCount, kTiffTagJpegOffset};
  // Parse the RAW data to get the ISO, offset and length of the preview image,
  // which contains the Exif information.
  const std::uint32_t kNumberOfIfds = 1;
  PreviewImageData preview_data;
  if (!GetPreviewData(extended_tags, kNumberOfIfds, stream, &preview_data)) {
    return kFail;
  }

  if (preview_data.preview.length > 0) {  // when preview image exists
    // Parse the Exif information from the preview image.
    const std::uint32_t exif_offset = preview_data.preview.offset + 12;
    if (!GetExifData(exif_offset, stream, preview_image_data)) {
      return kFail;
    }
    preview_image_data->thumbnail.offset += exif_offset;
  }

  // Merge the Exif data with the RAW data to form the preview_image_data.
  preview_image_data->preview = preview_data.preview;
  preview_image_data->iso = preview_data.iso;
  preview_image_data->full_width = preview_data.full_width;
  preview_image_data->full_height = preview_data.full_height;

  return kOk;
}

Error SrwGetPreviewData(StreamInterface* stream,
                        PreviewImageData* preview_image_data) {
  GetThumbnailOffsetAndLength({kTiffTagSubIfd}, stream, preview_image_data);

  const TagSet extended_tags = {kExifTagWidth, kExifTagHeight,
                                kTiffTagJpegByteCount, kTiffTagJpegOffset,
                                kTiffTagSubIfd};
  const std::uint32_t kNumberOfIfds = 1;
  if (!GetPreviewData(extended_tags, kNumberOfIfds, stream,
                      preview_image_data)) {
    return kFail;
  }
  return kOk;
}

}  // namespace

size_t BytesRequiredForIsRaw() {
  return image_type_recognition::GetNumberOfBytesForIsRawLite();
}

bool IsRaw(StreamInterface* data) {
  const size_t bytes = BytesRequiredForIsRaw();
  if (data == nullptr) {
    return false;
  }

  // Read required number of bytes into a vector.
  std::vector<std::uint8_t> file_header(bytes);
  if (data->GetData(0, file_header.size(), file_header.data()) != kOk) {
    return false;
  }

  RangeCheckedBytePtr data_buffer(file_header.data(), file_header.size());

  return image_type_recognition::IsRawLite(data_buffer);
}

Error GetPreviewImageData(StreamInterface* data,
                          PreviewImageData* preview_image_data,
                          RawImageTypes* output_type) {
  const size_t bytes = BytesRequiredForIsRaw();
  if (data == nullptr || bytes == 0) {
    return kFail;
  }

  std::vector<std::uint8_t> file_header(bytes);
  Error error = data->GetData(0, file_header.size(), file_header.data());
  if (error != kOk) {
    return error;
  }
  RangeCheckedBytePtr header_buffer(file_header.data(), file_header.size());

  RawImageTypes type = RecognizeRawImageTypeLite(header_buffer);
  if (output_type != nullptr) *output_type = type;
  switch (type) {
    case image_type_recognition::kArwImage:
      return ArwGetPreviewData(data, preview_image_data);
    case image_type_recognition::kCr2Image:
      return Cr2GetPreviewData(data, preview_image_data);
    case image_type_recognition::kCr3Image:
      return Cr3GetPreviewData(data, preview_image_data);
    case image_type_recognition::kDngImage:
      return DngGetPreviewData(data, preview_image_data);
    case image_type_recognition::kNefImage:
    case image_type_recognition::kNrwImage:
      return NefGetPreviewData(data, preview_image_data);
    case image_type_recognition::kOrfImage:
      return OrfGetPreviewData(data, preview_image_data);
    case image_type_recognition::kPefImage:
      return PefGetPreviewData(data, preview_image_data);
    case image_type_recognition::kRafImage:
      return RafGetPreviewData(data, preview_image_data);
    case image_type_recognition::kRw2Image:
      return Rw2GetPreviewData(data, preview_image_data);
    case image_type_recognition::kSrwImage:
      return SrwGetPreviewData(data, preview_image_data);
    default:
      return kUnsupported;
  }
}

bool GetDngInformation(StreamInterface* data, std::uint32_t* width,
                       std::uint32_t* height,
                       std::vector<std::uint32_t>* cfa_pattern_dim) {
  // If IFD0 contains already the full dimensions we do not parse into the sub
  // IFD.
  if (!GetDngInformation({}, data, width, height, cfa_pattern_dim)) {
    return GetDngInformation({kTiffTagSubIfd}, data, width, height,
                             cfa_pattern_dim);
  }
  return true;
}

bool GetOrientation(StreamInterface* data, std::uint32_t* orientation) {
  using image_type_recognition::GetNumberOfBytesForIsOfType;
  using image_type_recognition::IsOfType;

  size_t min_header_bytes =
      std::max(GetNumberOfBytesForIsOfType(image_type_recognition::kRafImage),
               GetNumberOfBytesForIsOfType(image_type_recognition::kCr3Image));

  std::vector<std::uint8_t> file_header(min_header_bytes);
  if (data->GetData(0, file_header.size(), file_header.data()) != kOk) {
    return false;
  }

  // For RAF and CR# files a special routine is necessary to get orientation.
  // For others the general approach is sufficient.
  if (IsOfType(RangeCheckedBytePtr(file_header.data(), file_header.size()),
               image_type_recognition::kRafImage)) {
    return RafGetOrientation(data, orientation);
  } else if (IsOfType(
                 RangeCheckedBytePtr(file_header.data(), file_header.size()),
                 image_type_recognition::kCr3Image)) {
    return Cr3GetOrientation(data, orientation);
  } else {
    return GetExifOrientation(data, 0 /* offset */, orientation);
  }
}

std::vector<std::string> SupportedExtensions() {
  return {"ARW", "CR2", "CR3", "DNG", "NEF", "NRW",
          "ORF", "PEF", "RAF", "RW2", "SRW"};
}

}  // namespace piex
