/*
 *  Copyright (c) 2008 Cyrille Berger <cberger@cberger.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * either version 2, or (at your option) any later version of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef _GTLIMAGEIO_IMAGE_DC_H_
#define _GTLIMAGEIO_IMAGE_DC_H_

#include <GTLCore/String.h>
#include <GTLImageIO/Export.h>

namespace GTLCore {
  class AbstractImage;
  class RegionI;
}

/**
 * Use this macro in your \ref ImageDC when an error occurs (it assumes that the variable
 * for error reporting is called _errorMessage), it will return false.
 */
#define TELL_ERROR( msg ) \
  if( _errorMessage ) *_errorMessage = msg; \
  return false

#define COND_TELL_ERROR( cond, msg ) \
  if( not (cond ) ) \
  { \
    TELL_ERROR( msg ); \
  }

namespace GTLImageIO {
  class Options;
  /**
   * Base class of Image Decoder / Coder .
   * @ingroup GTLImageIO
   */
  class GTLIMAGEIO_EXPORT ImageDC {
    public:
      ImageDC();
      virtual ~ImageDC();
      /**
       * Read file to disk.
       * @return a pointer to the image, and an error message if no data
       */
      virtual GTLCore::AbstractImage* decode( const GTLCore::String& _fileName, GTLCore::RegionI* _region = 0, GTLCore::String* _errorMessage = 0 ) const = 0;
      /**
       * This function will only check if the extension is in the list. If you want more
       * checking, you can reimplement in an herited class.
       *
       * @return true if this \ref ImageDC can decode images.
       */
      virtual bool canDecodeImage( const GTLCore::String& _fileName ) const;
      /**
       * Save file to disk.
       * @return false if an error has happen, and fill \param _errorMessage
       */
      virtual bool encode( const GTLCore::AbstractImage* _image, const GTLCore::RegionI& _region, const GTLCore::String& _fileName, const Options* _options = 0, GTLCore::String* _errorMessage = 0 ) const = 0;
      /**
       * This function will only check if the extension is in the list. If you want more
       * checking, you can reimplement in an herited class.
       *
       * @return true if this \ref ImageDC can encode images.
       */
      virtual bool canEncodeImage( const GTLCore::String& _fileName ) const;
      const GTLCore::String& decodableFilter() const;
      const GTLCore::String& encodableFilter() const;
    protected:
      /**
       * Add an extension that can be read by this \ref ImageDC .
       */
      void addReadExtension( const GTLCore::String& _extension );
      /**
       * Add an extension that can be written by this \ref ImageDC .
       */
      void addWriteExtension( const GTLCore::String& _extension );
      /**
       * Convenient function that call \ref addReadExtension and
       * \ref addWriteExtension with the \param _extension given in parameter.
       */
      void addReadWriteExtension( const GTLCore::String& _extension );
    private:
      GTLCore::String extension( const GTLCore::String& _fileName ) const;
    private:
      struct Private;
      Private *const d;
  };
}

#endif
