// ExifReader.h
// Copyright (c) 2009 The Foundry Visionmongers Ltd.  All Rights Reserved.

#include <libexif/exif-data.h>

#include <string>
#include <sstream>

#include "DDImage/Reader.h"

class ExifReader : public DD::Image::Reader
{
public:
  ExifReader(DD::Image::Read * iop);
  void fetchExifMetaData(DD::Image::MetaData::Bundle& metadata, void* data, int len);
};




ExifReader::ExifReader(DD::Image::Read * iop)
: DD::Image::Reader(iop)
{
}

void ExifReader::fetchExifMetaData(DD::Image::MetaData::Bundle& metadata, void* rawdata, int size)
{
  ExifData* data = exif_data_new_from_data((const unsigned char*)rawdata, size);
  if (!data) {
    return;
  }

  ExifByteOrder byteOrder = exif_data_get_byte_order(data);

  for (int i = 0; i < EXIF_IFD_COUNT; i++) {
    ExifContent* cont = data->ifd[i];
    for (size_t j = 0; j < cont->count; j++) {
      ExifEntry* entry = cont->entries[j];

      std::ostringstream str;

      switch (entry->format) {
        case EXIF_FORMAT_ASCII:
        {
          std::string asciistring = std::string((char*)entry->data, entry->size);

          if (asciistring.length() && asciistring[asciistring.length() - 1] == '\0') {
            asciistring = asciistring.substr(0, asciistring.length() - 1);
          }

          str << asciistring;
        }
        break;
        case EXIF_FORMAT_BYTE:
          str << (int)*entry->data;
          break;
        case EXIF_FORMAT_SHORT:
          str << exif_get_short(entry->data, byteOrder);
          break;
        case EXIF_FORMAT_LONG:
          str << exif_get_long(entry->data, byteOrder);
          break;
        case EXIF_FORMAT_SLONG:
          str << exif_get_slong(entry->data, byteOrder);
          break;
        case EXIF_FORMAT_RATIONAL:
        {
          ExifRational number = exif_get_rational(entry->data, byteOrder);
          str << number.numerator << "/" << number.denominator;
        }
        break;
        case EXIF_FORMAT_SRATIONAL:
        {
          ExifSRational number = exif_get_srational(entry->data, byteOrder);
          str << number.numerator << "/" << number.denominator;
        }
        break;
        default:
          ;
      }

      std::ostringstream key;
      key << DD::Image::MetaData::EXIF::EXIF_PREFIX;
      key << i;
      key << "/";
      key << exif_tag_get_name(entry->tag);

      metadata.setData(key.str(), str.str());
    }
  }

  exif_data_free(data);
}
