#ifndef n_ImageSource_H
#define n_ImageSource_H

/*
 *
 * nucleo/image/source/ImageSource.H --
 *
 * Copyright (C) Nicolas Roussel
 *
 * See the file LICENSE for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

#include <nucleo/core/URL.H>
#include <nucleo/core/ReactiveObject.H>
#include <nucleo/utils/TimeUtils.H>
#include <nucleo/image/Image.H>

namespace nucleo {

  // ------------------------------------------------------------------

  /*
   *
   * An image source should never throw any exception except in the
   * constructor. Warnings can be printed using cerr if anything goes
   * wrong. In that case, just mark the source as inactive.
   *
   * The constructor should set up the instance but not open any file
   * or network connection (use start() for this)
   *
   * Multiple start/.../stop should be possible...
   *
   * isActive() can be used by clients to know whether the source can
   * provide more images
   *
   * Whenever a new image is available, the source should call
   * notifyObservers
   *
   */

  class ImageSource : public ReactiveObject {

  protected:

    Chronometer _chrono ;

  public:

    ImageSource(void) {}
    virtual ~ImageSource(void) {}

    virtual bool start(void)=0 ;
    virtual bool getNextImage(Image *img )=0 ;
    virtual bool getLatestImage(Image *img) ;
    virtual bool isActive(void)=0 ;
    virtual bool stop(void)=0 ;

    bool waitForImage(Image *img, bool latest=false) ;

    void resetFrameRate(void) {
	 _chrono.start() ;
    }
    double getFrameRate(void) {
	 return _chrono.average() ;
    }
    double getFrameNumber(void) {
	 return _chrono.count() ;
    }

    static ImageSource *create(const char *url, Image::Encoding e=Image::PREFERRED) ;
    static ImageSource *create(std::string url, Image::Encoding e=Image::PREFERRED) {
	 return create(url.c_str(), e) ;
    }

    static bool getImage(const char *url, Image *img, Image::Encoding enc=Image::PREFERRED) ;
    static bool getImage(std::string url, Image *img, Image::Encoding enc=Image::PREFERRED) {
	 return getImage(url.c_str(), img, enc) ;
    }

  } ;

  typedef ImageSource * (*ImageSourceFactory) (const URL *url, Image::Encoding e) ;

  // ------------------------------------------------------------------

}

#endif
